Delete chrome.mediaGalleriesPrivate because the functionality unique to it has since...
[chromium-blink-merge.git] / media / base / android / media_player_bridge.cc
bloba9bf7e42900a7528ce284ee442aa8771b468d65a
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 "base/strings/string_util.h"
13 #include "jni/MediaPlayerBridge_jni.h"
14 #include "media/base/android/media_common_android.h"
15 #include "media/base/android/media_player_manager.h"
16 #include "media/base/android/media_resource_getter.h"
17 #include "media/base/android/media_url_interceptor.h"
18 #include "media/base/buffers.h"
20 using base::android::ConvertUTF8ToJavaString;
21 using base::android::ScopedJavaLocalRef;
23 namespace media {
25 MediaPlayerBridge::MediaPlayerBridge(
26 int player_id,
27 const GURL& url,
28 const GURL& first_party_for_cookies,
29 const std::string& user_agent,
30 bool hide_url_log,
31 MediaPlayerManager* manager,
32 const RequestMediaResourcesCB& request_media_resources_cb,
33 const GURL& frame_url,
34 bool allow_credentials)
35 : MediaPlayerAndroid(player_id,
36 manager,
37 request_media_resources_cb,
38 frame_url),
39 prepared_(false),
40 pending_play_(false),
41 should_seek_on_prepare_(false),
42 url_(url),
43 first_party_for_cookies_(first_party_for_cookies),
44 user_agent_(user_agent),
45 hide_url_log_(hide_url_log),
46 width_(0),
47 height_(0),
48 can_pause_(true),
49 can_seek_forward_(true),
50 can_seek_backward_(true),
51 volume_(-1.0),
52 allow_credentials_(allow_credentials),
53 weak_factory_(this) {
56 MediaPlayerBridge::~MediaPlayerBridge() {
57 if (!j_media_player_bridge_.is_null()) {
58 JNIEnv* env = base::android::AttachCurrentThread();
59 CHECK(env);
60 Java_MediaPlayerBridge_destroy(env, j_media_player_bridge_.obj());
62 Release();
65 void MediaPlayerBridge::Initialize() {
66 cookies_.clear();
67 if (url_.SchemeIsFile() || url_.SchemeIs("data")) {
68 ExtractMediaMetadata(url_.spec());
69 return;
72 media::MediaResourceGetter* resource_getter =
73 manager()->GetMediaResourceGetter();
74 if (url_.SchemeIsFileSystem() || url_.SchemeIsBlob()) {
75 resource_getter->GetPlatformPathFromURL(
76 url_,
77 base::Bind(&MediaPlayerBridge::ExtractMediaMetadata,
78 weak_factory_.GetWeakPtr()));
79 return;
82 // Start extracting the metadata immediately if the request is anonymous.
83 // Otherwise, wait for user credentials to be retrieved first.
84 if (!allow_credentials_) {
85 ExtractMediaMetadata(url_.spec());
86 return;
89 resource_getter->GetCookies(url_,
90 first_party_for_cookies_,
91 base::Bind(&MediaPlayerBridge::OnCookiesRetrieved,
92 weak_factory_.GetWeakPtr()));
95 void MediaPlayerBridge::CreateJavaMediaPlayerBridge() {
96 JNIEnv* env = base::android::AttachCurrentThread();
97 CHECK(env);
99 j_media_player_bridge_.Reset(Java_MediaPlayerBridge_create(
100 env, reinterpret_cast<intptr_t>(this)));
102 if (volume_ >= 0)
103 SetVolume(volume_);
105 AttachListener(j_media_player_bridge_.obj());
108 void MediaPlayerBridge::SetDuration(base::TimeDelta duration) {
109 duration_ = duration;
112 void MediaPlayerBridge::SetVideoSurface(gfx::ScopedJavaSurface surface) {
113 if (j_media_player_bridge_.is_null()) {
114 if (surface.IsEmpty())
115 return;
116 Prepare();
119 JNIEnv* env = base::android::AttachCurrentThread();
120 CHECK(env);
121 Java_MediaPlayerBridge_setSurface(
122 env, j_media_player_bridge_.obj(), surface.j_surface().obj());
125 void MediaPlayerBridge::Prepare() {
126 DCHECK(j_media_player_bridge_.is_null());
127 CreateJavaMediaPlayerBridge();
128 if (url_.SchemeIsFileSystem() || url_.SchemeIsBlob()) {
129 manager()->GetMediaResourceGetter()->GetPlatformPathFromURL(
130 url_,
131 base::Bind(&MediaPlayerBridge::SetDataSource,
132 weak_factory_.GetWeakPtr()));
133 return;
136 SetDataSource(url_.spec());
139 void MediaPlayerBridge::SetDataSource(const std::string& url) {
140 if (j_media_player_bridge_.is_null())
141 return;
143 JNIEnv* env = base::android::AttachCurrentThread();
144 CHECK(env);
146 int fd;
147 int64 offset;
148 int64 size;
149 if (InterceptMediaUrl(url, &fd, &offset, &size)) {
150 if (!Java_MediaPlayerBridge_setDataSourceFromFd(
151 env, j_media_player_bridge_.obj(), fd, offset, size)) {
152 OnMediaError(MEDIA_ERROR_FORMAT);
153 return;
155 } else {
156 // Create a Java String for the URL.
157 ScopedJavaLocalRef<jstring> j_url_string =
158 ConvertUTF8ToJavaString(env, url);
160 jobject j_context = base::android::GetApplicationContext();
161 DCHECK(j_context);
163 const std::string data_uri_prefix("data:");
164 if (StartsWithASCII(url, data_uri_prefix, true)) {
165 if (!Java_MediaPlayerBridge_setDataUriDataSource(
166 env, j_media_player_bridge_.obj(), j_context, j_url_string.obj())) {
167 OnMediaError(MEDIA_ERROR_FORMAT);
169 return;
172 ScopedJavaLocalRef<jstring> j_cookies = ConvertUTF8ToJavaString(
173 env, cookies_);
174 ScopedJavaLocalRef<jstring> j_user_agent = ConvertUTF8ToJavaString(
175 env, user_agent_);
177 if (!Java_MediaPlayerBridge_setDataSource(
178 env, j_media_player_bridge_.obj(), j_context, j_url_string.obj(),
179 j_cookies.obj(), j_user_agent.obj(), hide_url_log_)) {
180 OnMediaError(MEDIA_ERROR_FORMAT);
181 return;
185 request_media_resources_cb_.Run(player_id());
186 if (!Java_MediaPlayerBridge_prepareAsync(env, j_media_player_bridge_.obj()))
187 OnMediaError(MEDIA_ERROR_FORMAT);
190 bool MediaPlayerBridge::InterceptMediaUrl(
191 const std::string& url, int* fd, int64* offset, int64* size) {
192 // Sentinel value to check whether the output arguments have been set.
193 const int kUnsetValue = -1;
195 *fd = kUnsetValue;
196 *offset = kUnsetValue;
197 *size = kUnsetValue;
198 media::MediaUrlInterceptor* url_interceptor =
199 manager()->GetMediaUrlInterceptor();
200 if (url_interceptor && url_interceptor->Intercept(url, fd, offset, size)) {
201 DCHECK_NE(kUnsetValue, *fd);
202 DCHECK_NE(kUnsetValue, *offset);
203 DCHECK_NE(kUnsetValue, *size);
204 return true;
206 return false;
209 void MediaPlayerBridge::OnDidSetDataUriDataSource(JNIEnv* env, jobject obj,
210 jboolean success) {
211 if (!success) {
212 OnMediaError(MEDIA_ERROR_FORMAT);
213 return;
216 request_media_resources_cb_.Run(player_id());
217 if (!Java_MediaPlayerBridge_prepareAsync(env, j_media_player_bridge_.obj()))
218 OnMediaError(MEDIA_ERROR_FORMAT);
221 void MediaPlayerBridge::OnCookiesRetrieved(const std::string& cookies) {
222 cookies_ = cookies;
223 manager()->GetMediaResourceGetter()->GetAuthCredentials(
224 url_,
225 base::Bind(&MediaPlayerBridge::OnAuthCredentialsRetrieved,
226 weak_factory_.GetWeakPtr()));
229 void MediaPlayerBridge::OnAuthCredentialsRetrieved(
230 const base::string16& username, const base::string16& password) {
231 GURL::ReplacementsW replacements;
232 if (!username.empty()) {
233 replacements.SetUsernameStr(username);
234 if (!password.empty())
235 replacements.SetPasswordStr(password);
236 url_ = url_.ReplaceComponents(replacements);
238 ExtractMediaMetadata(url_.spec());
241 void MediaPlayerBridge::ExtractMediaMetadata(const std::string& url) {
242 if (url.empty()) {
243 OnMediaError(MEDIA_ERROR_FORMAT);
244 return;
247 int fd;
248 int64 offset;
249 int64 size;
250 if (InterceptMediaUrl(url, &fd, &offset, &size)) {
251 manager()->GetMediaResourceGetter()->ExtractMediaMetadata(
252 fd, offset, size,
253 base::Bind(&MediaPlayerBridge::OnMediaMetadataExtracted,
254 weak_factory_.GetWeakPtr()));
255 } else {
256 manager()->GetMediaResourceGetter()->ExtractMediaMetadata(
257 url, cookies_, user_agent_,
258 base::Bind(&MediaPlayerBridge::OnMediaMetadataExtracted,
259 weak_factory_.GetWeakPtr()));
263 void MediaPlayerBridge::OnMediaMetadataExtracted(
264 base::TimeDelta duration, int width, int height, bool success) {
265 if (success) {
266 duration_ = duration;
267 width_ = width;
268 height_ = height;
270 manager()->OnMediaMetadataChanged(
271 player_id(), duration_, width_, height_, success);
274 void MediaPlayerBridge::Start() {
275 if (j_media_player_bridge_.is_null()) {
276 pending_play_ = true;
277 Prepare();
278 } else {
279 if (prepared_)
280 StartInternal();
281 else
282 pending_play_ = true;
286 void MediaPlayerBridge::Pause(bool is_media_related_action) {
287 if (j_media_player_bridge_.is_null()) {
288 pending_play_ = false;
289 } else {
290 if (prepared_ && IsPlaying())
291 PauseInternal();
292 else
293 pending_play_ = false;
297 bool MediaPlayerBridge::IsPlaying() {
298 if (!prepared_)
299 return pending_play_;
301 JNIEnv* env = base::android::AttachCurrentThread();
302 CHECK(env);
303 jboolean result = Java_MediaPlayerBridge_isPlaying(
304 env, j_media_player_bridge_.obj());
305 return result;
308 int MediaPlayerBridge::GetVideoWidth() {
309 if (!prepared_)
310 return width_;
311 JNIEnv* env = base::android::AttachCurrentThread();
312 return Java_MediaPlayerBridge_getVideoWidth(
313 env, j_media_player_bridge_.obj());
316 int MediaPlayerBridge::GetVideoHeight() {
317 if (!prepared_)
318 return height_;
319 JNIEnv* env = base::android::AttachCurrentThread();
320 return Java_MediaPlayerBridge_getVideoHeight(
321 env, j_media_player_bridge_.obj());
324 void MediaPlayerBridge::SeekTo(base::TimeDelta timestamp) {
325 // Record the time to seek when OnMediaPrepared() is called.
326 pending_seek_ = timestamp;
327 should_seek_on_prepare_ = true;
329 if (j_media_player_bridge_.is_null())
330 Prepare();
331 else if (prepared_)
332 SeekInternal(timestamp);
335 base::TimeDelta MediaPlayerBridge::GetCurrentTime() {
336 if (!prepared_)
337 return pending_seek_;
338 JNIEnv* env = base::android::AttachCurrentThread();
339 return base::TimeDelta::FromMilliseconds(
340 Java_MediaPlayerBridge_getCurrentPosition(
341 env, j_media_player_bridge_.obj()));
344 base::TimeDelta MediaPlayerBridge::GetDuration() {
345 if (!prepared_)
346 return duration_;
347 JNIEnv* env = base::android::AttachCurrentThread();
348 const int duration_ms =
349 Java_MediaPlayerBridge_getDuration(env, j_media_player_bridge_.obj());
350 return duration_ms < 0 ? media::kInfiniteDuration()
351 : base::TimeDelta::FromMilliseconds(duration_ms);
354 void MediaPlayerBridge::Release() {
355 if (j_media_player_bridge_.is_null())
356 return;
358 time_update_timer_.Stop();
359 if (prepared_) {
360 pending_seek_ = GetCurrentTime();
361 should_seek_on_prepare_ = true;
364 prepared_ = false;
365 pending_play_ = false;
366 SetVideoSurface(gfx::ScopedJavaSurface());
367 JNIEnv* env = base::android::AttachCurrentThread();
368 Java_MediaPlayerBridge_release(env, j_media_player_bridge_.obj());
369 j_media_player_bridge_.Reset();
370 DetachListener();
373 void MediaPlayerBridge::SetVolume(double volume) {
374 if (j_media_player_bridge_.is_null()) {
375 volume_ = volume;
376 return;
379 JNIEnv* env = base::android::AttachCurrentThread();
380 CHECK(env);
381 Java_MediaPlayerBridge_setVolume(
382 env, j_media_player_bridge_.obj(), volume);
385 void MediaPlayerBridge::OnVideoSizeChanged(int width, int height) {
386 width_ = width;
387 height_ = height;
388 MediaPlayerAndroid::OnVideoSizeChanged(width, height);
391 void MediaPlayerBridge::OnPlaybackComplete() {
392 time_update_timer_.Stop();
393 MediaPlayerAndroid::OnPlaybackComplete();
396 void MediaPlayerBridge::OnMediaInterrupted() {
397 time_update_timer_.Stop();
398 MediaPlayerAndroid::OnMediaInterrupted();
401 void MediaPlayerBridge::OnMediaPrepared() {
402 if (j_media_player_bridge_.is_null())
403 return;
405 prepared_ = true;
406 duration_ = GetDuration();
408 // If media player was recovered from a saved state, consume all the pending
409 // events.
410 if (should_seek_on_prepare_) {
411 PendingSeekInternal(pending_seek_);
412 pending_seek_ = base::TimeDelta::FromMilliseconds(0);
413 should_seek_on_prepare_ = false;
416 if (pending_play_) {
417 StartInternal();
418 pending_play_ = false;
421 UpdateAllowedOperations();
422 manager()->OnMediaMetadataChanged(
423 player_id(), duration_, width_, height_, true);
426 ScopedJavaLocalRef<jobject> MediaPlayerBridge::GetAllowedOperations() {
427 JNIEnv* env = base::android::AttachCurrentThread();
428 CHECK(env);
430 return Java_MediaPlayerBridge_getAllowedOperations(
431 env, j_media_player_bridge_.obj());
434 void MediaPlayerBridge::UpdateAllowedOperations() {
435 JNIEnv* env = base::android::AttachCurrentThread();
436 CHECK(env);
438 ScopedJavaLocalRef<jobject> allowedOperations = GetAllowedOperations();
440 can_pause_ = Java_AllowedOperations_canPause(env, allowedOperations.obj());
441 can_seek_forward_ = Java_AllowedOperations_canSeekForward(
442 env, allowedOperations.obj());
443 can_seek_backward_ = Java_AllowedOperations_canSeekBackward(
444 env, allowedOperations.obj());
447 void MediaPlayerBridge::StartInternal() {
448 JNIEnv* env = base::android::AttachCurrentThread();
449 Java_MediaPlayerBridge_start(env, j_media_player_bridge_.obj());
450 if (!time_update_timer_.IsRunning()) {
451 time_update_timer_.Start(
452 FROM_HERE,
453 base::TimeDelta::FromMilliseconds(kTimeUpdateInterval),
454 this, &MediaPlayerBridge::OnTimeUpdateTimerFired);
458 void MediaPlayerBridge::PauseInternal() {
459 JNIEnv* env = base::android::AttachCurrentThread();
460 Java_MediaPlayerBridge_pause(env, j_media_player_bridge_.obj());
461 time_update_timer_.Stop();
464 void MediaPlayerBridge::PendingSeekInternal(const base::TimeDelta& time) {
465 SeekInternal(time);
468 void MediaPlayerBridge::SeekInternal(base::TimeDelta time) {
469 if (time > duration_)
470 time = duration_;
472 // Seeking to an invalid position may cause media player to stuck in an
473 // error state.
474 if (time < base::TimeDelta()) {
475 DCHECK_EQ(-1.0, time.InMillisecondsF());
476 return;
479 JNIEnv* env = base::android::AttachCurrentThread();
480 CHECK(env);
481 int time_msec = static_cast<int>(time.InMilliseconds());
482 Java_MediaPlayerBridge_seekTo(
483 env, j_media_player_bridge_.obj(), time_msec);
486 void MediaPlayerBridge::OnTimeUpdateTimerFired() {
487 manager()->OnTimeUpdate(
488 player_id(), GetCurrentTime(), base::TimeTicks::Now());
491 bool MediaPlayerBridge::RegisterMediaPlayerBridge(JNIEnv* env) {
492 return RegisterNativesImpl(env);
495 bool MediaPlayerBridge::CanPause() {
496 return can_pause_;
499 bool MediaPlayerBridge::CanSeekForward() {
500 return can_seek_forward_;
503 bool MediaPlayerBridge::CanSeekBackward() {
504 return can_seek_backward_;
507 bool MediaPlayerBridge::IsPlayerReady() {
508 return prepared_;
511 GURL MediaPlayerBridge::GetUrl() {
512 return url_;
515 GURL MediaPlayerBridge::GetFirstPartyForCookies() {
516 return first_party_for_cookies_;
519 } // namespace media