Home | History | Annotate | Download | only in android
      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 
     17 using base::android::AttachCurrentThread;
     18 using base::android::CheckException;
     19 using base::android::ScopedJavaGlobalRef;
     20 
     21 namespace content {
     22 
     23 namespace {
     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;
     27 
     28 }  // namespace
     29 
     30 static 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 
     37 bool ContentVideoView::RegisterContentVideoView(JNIEnv* env) {
     38   return RegisterNativesImpl(env);
     39 }
     40 
     41 ContentVideoView* ContentVideoView::GetInstance() {
     42   return g_content_video_view;
     43 }
     44 
     45 ContentVideoView::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 
     55 ContentVideoView::~ContentVideoView() {
     56   DCHECK(g_content_video_view);
     57   JNIEnv* env = AttachCurrentThread();
     58   ScopedJavaLocalRef<jobject> content_video_view = GetJavaObject(env);
     59   if (!content_video_view.is_null()) {
     60     Java_ContentVideoView_destroyContentVideoView(env,
     61         content_video_view.obj(), true);
     62     j_content_video_view_.reset();
     63   }
     64   g_content_video_view = NULL;
     65 }
     66 
     67 void ContentVideoView::OpenVideo() {
     68   JNIEnv* env = AttachCurrentThread();
     69   ScopedJavaLocalRef<jobject> content_video_view = GetJavaObject(env);
     70   if (!content_video_view.is_null()) {
     71     CreatePowerSaveBlocker();
     72     Java_ContentVideoView_openVideo(env, content_video_view.obj());
     73   }
     74 }
     75 
     76 void ContentVideoView::OnMediaPlayerError(int error_type) {
     77   JNIEnv* env = AttachCurrentThread();
     78   ScopedJavaLocalRef<jobject> content_video_view = GetJavaObject(env);
     79   if (!content_video_view.is_null()) {
     80     power_save_blocker_.reset();
     81     Java_ContentVideoView_onMediaPlayerError(env, content_video_view.obj(),
     82         error_type);
     83   }
     84 }
     85 
     86 void ContentVideoView::OnVideoSizeChanged(int width, int height) {
     87   JNIEnv* env = AttachCurrentThread();
     88   ScopedJavaLocalRef<jobject> content_video_view = GetJavaObject(env);
     89   if (!content_video_view.is_null()) {
     90     Java_ContentVideoView_onVideoSizeChanged(env, content_video_view.obj(),
     91         width, height);
     92   }
     93 }
     94 
     95 void ContentVideoView::OnBufferingUpdate(int percent) {
     96   JNIEnv* env = AttachCurrentThread();
     97   ScopedJavaLocalRef<jobject> content_video_view = GetJavaObject(env);
     98   if (!content_video_view.is_null()) {
     99     Java_ContentVideoView_onBufferingUpdate(env, content_video_view.obj(),
    100         percent);
    101   }
    102 }
    103 
    104 void ContentVideoView::OnPlaybackComplete() {
    105   JNIEnv* env = AttachCurrentThread();
    106   ScopedJavaLocalRef<jobject> content_video_view = GetJavaObject(env);
    107   if (!content_video_view.is_null()) {
    108     power_save_blocker_.reset();
    109     Java_ContentVideoView_onPlaybackComplete(env, content_video_view.obj());
    110   }
    111 }
    112 
    113 void ContentVideoView::OnExitFullscreen() {
    114   JNIEnv* env = AttachCurrentThread();
    115   ScopedJavaLocalRef<jobject> content_video_view = GetJavaObject(env);
    116   if (!content_video_view.is_null())
    117     Java_ContentVideoView_onExitFullscreen(env, content_video_view.obj());
    118 }
    119 
    120 void ContentVideoView::UpdateMediaMetadata() {
    121   JNIEnv* env = AttachCurrentThread();
    122   ScopedJavaLocalRef<jobject> content_video_view = GetJavaObject(env);
    123   if (content_video_view.is_null())
    124     return;
    125 
    126   media::MediaPlayerAndroid* player = manager_->GetFullscreenPlayer();
    127   if (player && player->IsPlayerReady()) {
    128     Java_ContentVideoView_onUpdateMediaMetadata(
    129         env, content_video_view.obj(), player->GetVideoWidth(),
    130         player->GetVideoHeight(),
    131         static_cast<int>(player->GetDuration().InMilliseconds()),
    132         player->CanPause(),player->CanSeekForward(), player->CanSeekBackward());
    133   }
    134 }
    135 
    136 int ContentVideoView::GetVideoWidth(JNIEnv*, jobject obj) const {
    137   media::MediaPlayerAndroid* player = manager_->GetFullscreenPlayer();
    138   return player ? player->GetVideoWidth() : 0;
    139 }
    140 
    141 int ContentVideoView::GetVideoHeight(JNIEnv*, jobject obj) const {
    142   media::MediaPlayerAndroid* player = manager_->GetFullscreenPlayer();
    143   return player ? player->GetVideoHeight() : 0;
    144 }
    145 
    146 int ContentVideoView::GetDurationInMilliSeconds(JNIEnv*, jobject obj) const {
    147   media::MediaPlayerAndroid* player = manager_->GetFullscreenPlayer();
    148   return player ? player->GetDuration().InMilliseconds() : -1;
    149 }
    150 
    151 int ContentVideoView::GetCurrentPosition(JNIEnv*, jobject obj) const {
    152   media::MediaPlayerAndroid* player = manager_->GetFullscreenPlayer();
    153   return player ? player->GetCurrentTime().InMilliseconds() : 0;
    154 }
    155 
    156 bool ContentVideoView::IsPlaying(JNIEnv*, jobject obj) {
    157   media::MediaPlayerAndroid* player = manager_->GetFullscreenPlayer();
    158   return player ? player->IsPlaying() : false;
    159 }
    160 
    161 void ContentVideoView::SeekTo(JNIEnv*, jobject obj, jint msec) {
    162   manager_->FullscreenPlayerSeek(msec);
    163 }
    164 
    165 void ContentVideoView::Play(JNIEnv*, jobject obj) {
    166   CreatePowerSaveBlocker();
    167   manager_->FullscreenPlayerPlay();
    168 }
    169 
    170 void ContentVideoView::Pause(JNIEnv*, jobject obj) {
    171   power_save_blocker_.reset();
    172   manager_->FullscreenPlayerPause();
    173 }
    174 
    175 void ContentVideoView::ExitFullscreen(
    176     JNIEnv*, jobject, jboolean release_media_player) {
    177   power_save_blocker_.reset();
    178   j_content_video_view_.reset();
    179   manager_->ExitFullscreen(release_media_player);
    180 }
    181 
    182 void ContentVideoView::SetSurface(JNIEnv* env, jobject obj,
    183                                   jobject surface) {
    184   manager_->SetVideoSurface(
    185       gfx::ScopedJavaSurface::AcquireExternalSurface(surface));
    186 }
    187 
    188 void ContentVideoView::RequestMediaMetadata(JNIEnv* env, jobject obj) {
    189   base::MessageLoop::current()->PostTask(
    190       FROM_HERE,
    191       base::Bind(&ContentVideoView::UpdateMediaMetadata,
    192                  weak_factory_.GetWeakPtr()));
    193 }
    194 
    195 ScopedJavaLocalRef<jobject> ContentVideoView::GetJavaObject(JNIEnv* env) {
    196   return j_content_video_view_.get(env);
    197 }
    198 
    199 gfx::NativeView ContentVideoView::GetNativeView() {
    200   JNIEnv* env = AttachCurrentThread();
    201   ScopedJavaLocalRef<jobject> content_video_view = GetJavaObject(env);
    202   if (content_video_view.is_null())
    203     return NULL;
    204 
    205   return reinterpret_cast<gfx::NativeView>(
    206       Java_ContentVideoView_getNativeViewAndroid(env,
    207                                                  content_video_view.obj()));
    208 
    209 }
    210 
    211 JavaObjectWeakGlobalRef ContentVideoView::CreateJavaObject() {
    212   ContentViewCoreImpl* content_view_core = manager_->GetContentViewCore();
    213   JNIEnv* env = AttachCurrentThread();
    214   bool legacyMode = CommandLine::ForCurrentProcess()->HasSwitch(
    215       switches::kDisableOverlayFullscreenVideoSubtitle);
    216   return JavaObjectWeakGlobalRef(
    217       env,
    218       Java_ContentVideoView_createContentVideoView(
    219           env,
    220           content_view_core->GetContext().obj(),
    221           reinterpret_cast<intptr_t>(this),
    222           content_view_core->GetContentVideoViewClient().obj(),
    223           legacyMode).obj());
    224 }
    225 
    226 void ContentVideoView::CreatePowerSaveBlocker() {
    227   if (CommandLine::ForCurrentProcess()->HasSwitch(
    228       switches::kEnableContentVideoViewPowerSaveBlocker)) {
    229     // In fullscreen Clank reuses the power save blocker attached to the
    230     // container view that was created for embedded video. The WebView cannot
    231     // reuse that so we create a new blocker instead.
    232     if (power_save_blocker_) return;
    233 
    234     power_save_blocker_ = PowerSaveBlocker::Create(
    235         PowerSaveBlocker::kPowerSaveBlockPreventDisplaySleep,
    236         "Playing video").Pass();
    237     static_cast<PowerSaveBlockerImpl*>(power_save_blocker_.get())->
    238         InitDisplaySleepBlocker(GetNativeView());
    239   }
    240 }
    241 }  // namespace content
    242