Fix for browser_plugin_host_browsertest when embedder is not yet available.
[chromium-blink-merge.git] / media / base / android / media_player_bridge.cc
blobdddb8a9f13bdd358dfccefe5c753cd0da87ac803
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 "media/base/android/media_player_bridge.h"
7 #include "base/android/jni_android.h"
8 #include "base/android/jni_string.h"
9 #include "base/basictypes.h"
10 #include "base/logging.h"
11 #include "base/message_loop/message_loop_proxy.h"
12 #include "jni/MediaPlayerBridge_jni.h"
13 #include "media/base/android/media_player_manager.h"
14 #include "media/base/android/media_resource_getter.h"
16 using base::android::ConvertUTF8ToJavaString;
17 using base::android::ScopedJavaLocalRef;
19 // Time update happens every 250ms.
20 static const int kTimeUpdateInterval = 250;
22 namespace media {
24 MediaPlayerBridge::MediaPlayerBridge(
25 int player_id,
26 const GURL& url,
27 const GURL& first_party_for_cookies,
28 bool hide_url_log,
29 MediaPlayerManager* manager)
30 : MediaPlayerAndroid(player_id,
31 manager),
32 prepared_(false),
33 pending_play_(false),
34 url_(url),
35 first_party_for_cookies_(first_party_for_cookies),
36 hide_url_log_(hide_url_log),
37 width_(0),
38 height_(0),
39 can_pause_(true),
40 can_seek_forward_(true),
41 can_seek_backward_(true),
42 weak_this_(this),
43 listener_(base::MessageLoopProxy::current(),
44 weak_this_.GetWeakPtr()) {
47 MediaPlayerBridge::~MediaPlayerBridge() {
48 Release();
51 void MediaPlayerBridge::Initialize() {
52 if (url_.SchemeIsFile()) {
53 cookies_.clear();
54 ExtractMediaMetadata(url_.spec());
55 return;
58 media::MediaResourceGetter* resource_getter =
59 manager()->GetMediaResourceGetter();
60 if (url_.SchemeIsFileSystem()) {
61 cookies_.clear();
62 resource_getter->GetPlatformPathFromFileSystemURL(url_, base::Bind(
63 &MediaPlayerBridge::ExtractMediaMetadata, weak_this_.GetWeakPtr()));
64 return;
67 resource_getter->GetCookies(url_, first_party_for_cookies_, base::Bind(
68 &MediaPlayerBridge::OnCookiesRetrieved, weak_this_.GetWeakPtr()));
71 void MediaPlayerBridge::CreateJavaMediaPlayerBridge() {
72 JNIEnv* env = base::android::AttachCurrentThread();
73 CHECK(env);
75 j_media_player_bridge_.Reset(Java_MediaPlayerBridge_create(env));
77 SetMediaPlayerListener();
80 void MediaPlayerBridge::SetJavaMediaPlayerBridge(
81 jobject j_media_player_bridge) {
82 JNIEnv* env = base::android::AttachCurrentThread();
83 CHECK(env);
85 j_media_player_bridge_.Reset(env, j_media_player_bridge);
88 void MediaPlayerBridge::SetMediaPlayerListener() {
89 jobject j_context = base::android::GetApplicationContext();
90 DCHECK(j_context);
92 listener_.CreateMediaPlayerListener(j_context, j_media_player_bridge_.obj());
95 void MediaPlayerBridge::SetDuration(base::TimeDelta duration) {
96 duration_ = duration;
99 void MediaPlayerBridge::SetVideoSurface(gfx::ScopedJavaSurface surface) {
100 if (j_media_player_bridge_.is_null()) {
101 if (surface.IsEmpty())
102 return;
103 Prepare();
106 JNIEnv* env = base::android::AttachCurrentThread();
107 CHECK(env);
109 Java_MediaPlayerBridge_setSurface(
110 env, j_media_player_bridge_.obj(), surface.j_surface().obj());
113 void MediaPlayerBridge::Prepare() {
114 if (j_media_player_bridge_.is_null())
115 CreateJavaMediaPlayerBridge();
116 if (url_.SchemeIsFileSystem()) {
117 manager()->GetMediaResourceGetter()->GetPlatformPathFromFileSystemURL(
118 url_, base::Bind(&MediaPlayerBridge::SetDataSource,
119 weak_this_.GetWeakPtr()));
120 } else {
121 SetDataSource(url_.spec());
125 void MediaPlayerBridge::SetDataSource(const std::string& url) {
126 if (j_media_player_bridge_.is_null())
127 return;
129 JNIEnv* env = base::android::AttachCurrentThread();
130 CHECK(env);
132 // Create a Java String for the URL.
133 ScopedJavaLocalRef<jstring> j_url_string = ConvertUTF8ToJavaString(env, url);
134 ScopedJavaLocalRef<jstring> j_cookies = ConvertUTF8ToJavaString(
135 env, cookies_);
137 jobject j_context = base::android::GetApplicationContext();
138 DCHECK(j_context);
140 if (Java_MediaPlayerBridge_setDataSource(
141 env, j_media_player_bridge_.obj(), j_context, j_url_string.obj(),
142 j_cookies.obj(), hide_url_log_)) {
143 manager()->RequestMediaResources(player_id());
144 Java_MediaPlayerBridge_prepareAsync(
145 env, j_media_player_bridge_.obj());
146 } else {
147 OnMediaError(MEDIA_ERROR_FORMAT);
151 void MediaPlayerBridge::OnCookiesRetrieved(const std::string& cookies) {
152 cookies_ = cookies;
153 ExtractMediaMetadata(url_.spec());
156 void MediaPlayerBridge::ExtractMediaMetadata(const std::string& url) {
157 manager()->GetMediaResourceGetter()->ExtractMediaMetadata(
158 url, cookies_, base::Bind(&MediaPlayerBridge::OnMediaMetadataExtracted,
159 weak_this_.GetWeakPtr()));
162 void MediaPlayerBridge::OnMediaMetadataExtracted(
163 base::TimeDelta duration, int width, int height, bool success) {
164 if (success) {
165 duration_ = duration;
166 width_ = width;
167 height_ = height;
169 manager()->OnMediaMetadataChanged(
170 player_id(), duration_, width_, height_, success);
173 void MediaPlayerBridge::Start() {
174 if (j_media_player_bridge_.is_null()) {
175 pending_play_ = true;
176 Prepare();
177 } else {
178 if (prepared_)
179 StartInternal();
180 else
181 pending_play_ = true;
185 void MediaPlayerBridge::Pause(bool is_media_related_action) {
186 if (j_media_player_bridge_.is_null()) {
187 pending_play_ = false;
188 } else {
189 if (prepared_ && IsPlaying())
190 PauseInternal();
191 else
192 pending_play_ = false;
196 bool MediaPlayerBridge::IsPlaying() {
197 if (!prepared_)
198 return pending_play_;
200 JNIEnv* env = base::android::AttachCurrentThread();
201 CHECK(env);
202 jboolean result = Java_MediaPlayerBridge_isPlaying(
203 env, j_media_player_bridge_.obj());
204 return result;
207 int MediaPlayerBridge::GetVideoWidth() {
208 if (!prepared_)
209 return width_;
210 JNIEnv* env = base::android::AttachCurrentThread();
211 return Java_MediaPlayerBridge_getVideoWidth(
212 env, j_media_player_bridge_.obj());
215 int MediaPlayerBridge::GetVideoHeight() {
216 if (!prepared_)
217 return height_;
218 JNIEnv* env = base::android::AttachCurrentThread();
219 return Java_MediaPlayerBridge_getVideoHeight(
220 env, j_media_player_bridge_.obj());
223 void MediaPlayerBridge::SeekTo(const base::TimeDelta& timestamp) {
224 // Record the time to seek when OnMediaPrepared() is called.
225 pending_seek_ = timestamp;
227 if (j_media_player_bridge_.is_null())
228 Prepare();
229 else if (prepared_)
230 SeekInternal(timestamp);
233 base::TimeDelta MediaPlayerBridge::GetCurrentTime() {
234 if (!prepared_)
235 return pending_seek_;
236 JNIEnv* env = base::android::AttachCurrentThread();
237 return base::TimeDelta::FromMilliseconds(
238 Java_MediaPlayerBridge_getCurrentPosition(
239 env, j_media_player_bridge_.obj()));
242 base::TimeDelta MediaPlayerBridge::GetDuration() {
243 if (!prepared_)
244 return duration_;
245 JNIEnv* env = base::android::AttachCurrentThread();
246 return base::TimeDelta::FromMilliseconds(
247 Java_MediaPlayerBridge_getDuration(
248 env, j_media_player_bridge_.obj()));
251 void MediaPlayerBridge::Release() {
252 if (j_media_player_bridge_.is_null())
253 return;
255 time_update_timer_.Stop();
256 if (prepared_)
257 pending_seek_ = GetCurrentTime();
258 prepared_ = false;
259 pending_play_ = false;
260 SetVideoSurface(gfx::ScopedJavaSurface());
262 JNIEnv* env = base::android::AttachCurrentThread();
263 Java_MediaPlayerBridge_release(env, j_media_player_bridge_.obj());
264 j_media_player_bridge_.Reset();
265 manager()->ReleaseMediaResources(player_id());
266 listener_.ReleaseMediaPlayerListenerResources();
269 void MediaPlayerBridge::SetVolume(double volume) {
270 if (j_media_player_bridge_.is_null())
271 return;
273 JNIEnv* env = base::android::AttachCurrentThread();
274 CHECK(env);
275 Java_MediaPlayerBridge_setVolume(
276 env, j_media_player_bridge_.obj(), volume);
279 void MediaPlayerBridge::OnVideoSizeChanged(int width, int height) {
280 width_ = width;
281 height_ = height;
282 manager()->OnVideoSizeChanged(player_id(), width, height);
285 void MediaPlayerBridge::OnMediaError(int error_type) {
286 manager()->OnError(player_id(), error_type);
289 void MediaPlayerBridge::OnBufferingUpdate(int percent) {
290 manager()->OnBufferingUpdate(player_id(), percent);
293 void MediaPlayerBridge::OnPlaybackComplete() {
294 time_update_timer_.Stop();
295 manager()->OnPlaybackComplete(player_id());
298 void MediaPlayerBridge::OnMediaInterrupted() {
299 time_update_timer_.Stop();
300 manager()->OnMediaInterrupted(player_id());
303 void MediaPlayerBridge::OnSeekComplete() {
304 manager()->OnSeekComplete(player_id(), GetCurrentTime());
307 void MediaPlayerBridge::OnMediaPrepared() {
308 if (j_media_player_bridge_.is_null())
309 return;
311 prepared_ = true;
312 duration_ = GetDuration();
314 // If media player was recovered from a saved state, consume all the pending
315 // events.
316 PendingSeekInternal(pending_seek_);
318 if (pending_play_) {
319 StartInternal();
320 pending_play_ = false;
323 GetAllowedOperations();
324 manager()->OnMediaMetadataChanged(
325 player_id(), duration_, width_, height_, true);
328 void MediaPlayerBridge::GetAllowedOperations() {
329 JNIEnv* env = base::android::AttachCurrentThread();
330 CHECK(env);
332 ScopedJavaLocalRef<jobject> allowedOperations =
333 Java_MediaPlayerBridge_getAllowedOperations(
334 env, j_media_player_bridge_.obj());
335 can_pause_ = Java_AllowedOperations_canPause(env, allowedOperations.obj());
336 can_seek_forward_ = Java_AllowedOperations_canSeekForward(
337 env, allowedOperations.obj());
338 can_seek_backward_ = Java_AllowedOperations_canSeekBackward(
339 env, allowedOperations.obj());
342 void MediaPlayerBridge::StartInternal() {
343 JNIEnv* env = base::android::AttachCurrentThread();
344 Java_MediaPlayerBridge_start(env, j_media_player_bridge_.obj());
345 if (!time_update_timer_.IsRunning()) {
346 time_update_timer_.Start(
347 FROM_HERE,
348 base::TimeDelta::FromMilliseconds(kTimeUpdateInterval),
349 this, &MediaPlayerBridge::OnTimeUpdateTimerFired);
353 void MediaPlayerBridge::PauseInternal() {
354 JNIEnv* env = base::android::AttachCurrentThread();
355 Java_MediaPlayerBridge_pause(env, j_media_player_bridge_.obj());
356 time_update_timer_.Stop();
359 void MediaPlayerBridge::PendingSeekInternal(const base::TimeDelta& time) {
360 SeekInternal(time);
363 void MediaPlayerBridge::SeekInternal(base::TimeDelta time) {
364 if (time > duration_)
365 time = duration_;
367 // Seeking to an invalid position may cause media player to stuck in an
368 // error state.
369 if (time < base::TimeDelta()) {
370 DCHECK_EQ(-1.0, time.InMillisecondsF());
371 return;
374 JNIEnv* env = base::android::AttachCurrentThread();
375 CHECK(env);
376 int time_msec = static_cast<int>(time.InMilliseconds());
377 Java_MediaPlayerBridge_seekTo(
378 env, j_media_player_bridge_.obj(), time_msec);
381 void MediaPlayerBridge::OnTimeUpdateTimerFired() {
382 manager()->OnTimeUpdate(player_id(), GetCurrentTime());
385 bool MediaPlayerBridge::RegisterMediaPlayerBridge(JNIEnv* env) {
386 bool ret = RegisterNativesImpl(env);
387 DCHECK(g_MediaPlayerBridge_clazz);
388 return ret;
391 bool MediaPlayerBridge::CanPause() {
392 return can_pause_;
395 bool MediaPlayerBridge::CanSeekForward() {
396 return can_seek_forward_;
399 bool MediaPlayerBridge::CanSeekBackward() {
400 return can_seek_backward_;
403 bool MediaPlayerBridge::IsPlayerReady() {
404 return prepared_;
407 GURL MediaPlayerBridge::GetUrl() {
408 return url_;
411 GURL MediaPlayerBridge::GetFirstPartyForCookies() {
412 return first_party_for_cookies_;
415 } // namespace media