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;
24 MediaPlayerBridge::MediaPlayerBridge(
27 const GURL& first_party_for_cookies,
29 MediaPlayerManager* manager)
30 : MediaPlayerAndroid(player_id,
35 first_party_for_cookies_(first_party_for_cookies),
36 hide_url_log_(hide_url_log),
40 can_seek_forward_(true),
41 can_seek_backward_(true),
43 listener_(base::MessageLoopProxy::current(),
44 weak_this_.GetWeakPtr()) {
47 MediaPlayerBridge::~MediaPlayerBridge() {
51 void MediaPlayerBridge::Initialize() {
52 if (url_.SchemeIsFile()) {
54 ExtractMediaMetadata(url_.spec());
58 media::MediaResourceGetter* resource_getter =
59 manager()->GetMediaResourceGetter();
60 if (url_.SchemeIsFileSystem()) {
62 resource_getter->GetPlatformPathFromFileSystemURL(url_, base::Bind(
63 &MediaPlayerBridge::ExtractMediaMetadata, weak_this_.GetWeakPtr()));
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();
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();
85 j_media_player_bridge_.Reset(env, j_media_player_bridge);
88 base::android::ScopedJavaLocalRef<jobject> MediaPlayerBridge::
89 GetJavaMediaPlayerBridge() {
90 base::android::ScopedJavaLocalRef<jobject> j_bridge(
91 j_media_player_bridge_);
95 void MediaPlayerBridge::SetMediaPlayerListener() {
96 jobject j_context = base::android::GetApplicationContext();
99 listener_.CreateMediaPlayerListener(j_context, j_media_player_bridge_.obj());
102 void MediaPlayerBridge::SetDuration(base::TimeDelta duration) {
103 duration_ = duration;
106 void MediaPlayerBridge::SetVideoSurface(gfx::ScopedJavaSurface surface) {
107 if (j_media_player_bridge_.is_null()) {
108 if (surface.IsEmpty())
113 JNIEnv* env = base::android::AttachCurrentThread();
116 Java_MediaPlayerBridge_setSurface(
117 env, j_media_player_bridge_.obj(), surface.j_surface().obj());
120 void MediaPlayerBridge::Prepare() {
121 if (j_media_player_bridge_.is_null())
122 CreateJavaMediaPlayerBridge();
123 if (url_.SchemeIsFileSystem()) {
124 manager()->GetMediaResourceGetter()->GetPlatformPathFromFileSystemURL(
125 url_, base::Bind(&MediaPlayerBridge::SetDataSource,
126 weak_this_.GetWeakPtr()));
128 SetDataSource(url_.spec());
132 void MediaPlayerBridge::SetDataSource(const std::string& url) {
133 if (j_media_player_bridge_.is_null())
136 JNIEnv* env = base::android::AttachCurrentThread();
139 // Create a Java String for the URL.
140 ScopedJavaLocalRef<jstring> j_url_string = ConvertUTF8ToJavaString(env, url);
141 ScopedJavaLocalRef<jstring> j_cookies = ConvertUTF8ToJavaString(
144 jobject j_context = base::android::GetApplicationContext();
147 if (Java_MediaPlayerBridge_setDataSource(
148 env, j_media_player_bridge_.obj(), j_context, j_url_string.obj(),
149 j_cookies.obj(), hide_url_log_)) {
150 manager()->RequestMediaResources(player_id());
151 Java_MediaPlayerBridge_prepareAsync(
152 env, j_media_player_bridge_.obj());
154 OnMediaError(MEDIA_ERROR_FORMAT);
158 void MediaPlayerBridge::OnCookiesRetrieved(const std::string& cookies) {
160 ExtractMediaMetadata(url_.spec());
163 void MediaPlayerBridge::ExtractMediaMetadata(const std::string& url) {
164 manager()->GetMediaResourceGetter()->ExtractMediaMetadata(
165 url, cookies_, base::Bind(&MediaPlayerBridge::OnMediaMetadataExtracted,
166 weak_this_.GetWeakPtr()));
169 void MediaPlayerBridge::OnMediaMetadataExtracted(
170 base::TimeDelta duration, int width, int height, bool success) {
172 duration_ = duration;
176 manager()->OnMediaMetadataChanged(
177 player_id(), duration_, width_, height_, success);
180 void MediaPlayerBridge::Start() {
181 if (j_media_player_bridge_.is_null()) {
182 pending_play_ = true;
188 pending_play_ = true;
192 void MediaPlayerBridge::Pause(bool is_media_related_action) {
193 if (j_media_player_bridge_.is_null()) {
194 pending_play_ = false;
196 if (prepared_ && IsPlaying())
199 pending_play_ = false;
203 bool MediaPlayerBridge::IsPlaying() {
205 return pending_play_;
207 JNIEnv* env = base::android::AttachCurrentThread();
209 jboolean result = Java_MediaPlayerBridge_isPlaying(
210 env, j_media_player_bridge_.obj());
214 int MediaPlayerBridge::GetVideoWidth() {
217 JNIEnv* env = base::android::AttachCurrentThread();
218 return Java_MediaPlayerBridge_getVideoWidth(
219 env, j_media_player_bridge_.obj());
222 int MediaPlayerBridge::GetVideoHeight() {
225 JNIEnv* env = base::android::AttachCurrentThread();
226 return Java_MediaPlayerBridge_getVideoHeight(
227 env, j_media_player_bridge_.obj());
230 void MediaPlayerBridge::SeekTo(const base::TimeDelta& timestamp) {
231 // Record the time to seek when OnMediaPrepared() is called.
232 pending_seek_ = timestamp;
234 if (j_media_player_bridge_.is_null())
237 SeekInternal(timestamp);
240 base::TimeDelta MediaPlayerBridge::GetCurrentTime() {
242 return pending_seek_;
243 JNIEnv* env = base::android::AttachCurrentThread();
244 return base::TimeDelta::FromMilliseconds(
245 Java_MediaPlayerBridge_getCurrentPosition(
246 env, j_media_player_bridge_.obj()));
249 base::TimeDelta MediaPlayerBridge::GetDuration() {
252 JNIEnv* env = base::android::AttachCurrentThread();
253 return base::TimeDelta::FromMilliseconds(
254 Java_MediaPlayerBridge_getDuration(
255 env, j_media_player_bridge_.obj()));
258 void MediaPlayerBridge::Release() {
259 if (j_media_player_bridge_.is_null())
262 time_update_timer_.Stop();
264 pending_seek_ = GetCurrentTime();
266 pending_play_ = false;
267 SetVideoSurface(gfx::ScopedJavaSurface());
269 JNIEnv* env = base::android::AttachCurrentThread();
270 Java_MediaPlayerBridge_release(env, j_media_player_bridge_.obj());
271 j_media_player_bridge_.Reset();
272 manager()->ReleaseMediaResources(player_id());
273 listener_.ReleaseMediaPlayerListenerResources();
276 void MediaPlayerBridge::SetVolume(double volume) {
277 if (j_media_player_bridge_.is_null())
280 JNIEnv* env = base::android::AttachCurrentThread();
282 Java_MediaPlayerBridge_setVolume(
283 env, j_media_player_bridge_.obj(), volume);
286 void MediaPlayerBridge::OnVideoSizeChanged(int width, int height) {
289 manager()->OnVideoSizeChanged(player_id(), width, height);
292 void MediaPlayerBridge::OnMediaError(int error_type) {
293 manager()->OnError(player_id(), error_type);
296 void MediaPlayerBridge::OnBufferingUpdate(int percent) {
297 manager()->OnBufferingUpdate(player_id(), percent);
300 void MediaPlayerBridge::OnPlaybackComplete() {
301 time_update_timer_.Stop();
302 manager()->OnPlaybackComplete(player_id());
305 void MediaPlayerBridge::OnMediaInterrupted() {
306 time_update_timer_.Stop();
307 manager()->OnMediaInterrupted(player_id());
310 void MediaPlayerBridge::OnSeekComplete() {
311 manager()->OnSeekComplete(player_id(), GetCurrentTime());
314 void MediaPlayerBridge::OnMediaPrepared() {
315 if (j_media_player_bridge_.is_null())
319 duration_ = GetDuration();
321 // If media player was recovered from a saved state, consume all the pending
323 PendingSeekInternal(pending_seek_);
327 pending_play_ = false;
330 UpdateAllowedOperations();
331 manager()->OnMediaMetadataChanged(
332 player_id(), duration_, width_, height_, true);
335 ScopedJavaLocalRef<jobject> MediaPlayerBridge::GetAllowedOperations() {
336 JNIEnv* env = base::android::AttachCurrentThread();
339 return Java_MediaPlayerBridge_getAllowedOperations(
340 env, j_media_player_bridge_.obj());
343 void MediaPlayerBridge::UpdateAllowedOperations() {
344 JNIEnv* env = base::android::AttachCurrentThread();
347 ScopedJavaLocalRef<jobject> allowedOperations = GetAllowedOperations();
349 can_pause_ = Java_AllowedOperations_canPause(env, allowedOperations.obj());
350 can_seek_forward_ = Java_AllowedOperations_canSeekForward(
351 env, allowedOperations.obj());
352 can_seek_backward_ = Java_AllowedOperations_canSeekBackward(
353 env, allowedOperations.obj());
356 void MediaPlayerBridge::StartInternal() {
357 JNIEnv* env = base::android::AttachCurrentThread();
358 Java_MediaPlayerBridge_start(env, j_media_player_bridge_.obj());
359 if (!time_update_timer_.IsRunning()) {
360 time_update_timer_.Start(
362 base::TimeDelta::FromMilliseconds(kTimeUpdateInterval),
363 this, &MediaPlayerBridge::OnTimeUpdateTimerFired);
367 void MediaPlayerBridge::PauseInternal() {
368 JNIEnv* env = base::android::AttachCurrentThread();
369 Java_MediaPlayerBridge_pause(env, j_media_player_bridge_.obj());
370 time_update_timer_.Stop();
373 void MediaPlayerBridge::PendingSeekInternal(const base::TimeDelta& time) {
377 void MediaPlayerBridge::SeekInternal(base::TimeDelta time) {
378 if (time > duration_)
381 // Seeking to an invalid position may cause media player to stuck in an
383 if (time < base::TimeDelta()) {
384 DCHECK_EQ(-1.0, time.InMillisecondsF());
388 JNIEnv* env = base::android::AttachCurrentThread();
390 int time_msec = static_cast<int>(time.InMilliseconds());
391 Java_MediaPlayerBridge_seekTo(
392 env, j_media_player_bridge_.obj(), time_msec);
395 void MediaPlayerBridge::OnTimeUpdateTimerFired() {
396 manager()->OnTimeUpdate(player_id(), GetCurrentTime());
399 bool MediaPlayerBridge::RegisterMediaPlayerBridge(JNIEnv* env) {
400 bool ret = RegisterNativesImpl(env);
401 DCHECK(g_MediaPlayerBridge_clazz);
405 bool MediaPlayerBridge::CanPause() {
409 bool MediaPlayerBridge::CanSeekForward() {
410 return can_seek_forward_;
413 bool MediaPlayerBridge::CanSeekBackward() {
414 return can_seek_backward_;
417 bool MediaPlayerBridge::IsPlayerReady() {
421 GURL MediaPlayerBridge::GetUrl() {
425 GURL MediaPlayerBridge::GetFirstPartyForCookies() {
426 return first_party_for_cookies_;