| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "media/base/android/media_player_bridge.h" | 5 #include "media/base/android/media_player_bridge.h" |
| 6 | 6 |
| 7 #include "base/android/jni_android.h" | 7 #include "base/android/jni_android.h" |
| 8 #include "base/android/jni_string.h" | 8 #include "base/android/jni_string.h" |
| 9 #include "base/basictypes.h" | 9 #include "base/basictypes.h" |
| 10 #include "base/logging.h" | 10 #include "base/logging.h" |
| 11 #include "base/stringprintf.h" | 11 #include "base/stringprintf.h" |
| 12 #include "base/message_loop_proxy.h" | 12 #include "base/message_loop_proxy.h" |
| 13 #include "jni/MediaPlayerBridge_jni.h" |
| 13 #include "media/base/android/cookie_getter.h" | 14 #include "media/base/android/cookie_getter.h" |
| 14 #include "media/base/android/media_player_bridge_manager.h" | 15 #include "media/base/android/media_player_bridge_manager.h" |
| 15 | 16 |
| 16 using base::android::AttachCurrentThread; | 17 using base::android::AttachCurrentThread; |
| 17 using base::android::CheckException; | 18 using base::android::CheckException; |
| 18 using base::android::ConvertUTF8ToJavaString; | 19 using base::android::ConvertUTF8ToJavaString; |
| 19 using base::android::GetClass; | 20 using base::android::GetClass; |
| 20 using base::android::GetMethodID; | 21 using base::android::GetMethodID; |
| 21 using base::android::JavaRef; | 22 using base::android::JavaRef; |
| 22 using base::android::ScopedJavaLocalRef; | 23 using base::android::ScopedJavaLocalRef; |
| 23 | 24 |
| 24 // These constants are from the android source tree and need to be kept in | 25 // These constants are from the android source tree and need to be kept in |
| 25 // sync with android/media/MediaMetadata.java. | 26 // sync with android/media/MediaMetadata.java. |
| 26 static const jint kPauseAvailable = 1; | 27 static const jint kPauseAvailable = 1; |
| 27 static const jint kSeekBackwardAvailable = 2; | 28 static const jint kSeekBackwardAvailable = 2; |
| 28 static const jint kSeekForwardAvailable = 3; | 29 static const jint kSeekForwardAvailable = 3; |
| 29 | 30 |
| 30 // This needs to be kept in sync with android.os.PowerManager | |
| 31 static const int kAndroidFullWakeLock = 26; | |
| 32 | |
| 33 // Time update happens every 250ms. | 31 // Time update happens every 250ms. |
| 34 static const int kTimeUpdateInterval = 250; | 32 static const int kTimeUpdateInterval = 250; |
| 35 | 33 |
| 36 // Because we create the media player lazily on android, the duration of the | 34 // Because we create the media player lazily on android, the duration of the |
| 37 // media is initially unknown to us. This makes the user unable to perform | 35 // media is initially unknown to us. This makes the user unable to perform |
| 38 // seek. To solve this problem, we use a temporary duration of 100 seconds when | 36 // seek. To solve this problem, we use a temporary duration of 100 seconds when |
| 39 // the duration is unknown. And we scale the seek position later when duration | 37 // the duration is unknown. And we scale the seek position later when duration |
| 40 // is available. | 38 // is available. |
| 41 // TODO(qinmin): create a thread and use android MediaMetadataRetriever | 39 // TODO(qinmin): create a thread and use android MediaMetadataRetriever |
| 42 // class to extract the duration. | 40 // class to extract the duration. |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 91 void MediaPlayerBridge::InitializePlayer() { | 89 void MediaPlayerBridge::InitializePlayer() { |
| 92 JNIEnv* env = AttachCurrentThread(); | 90 JNIEnv* env = AttachCurrentThread(); |
| 93 CHECK(env); | 91 CHECK(env); |
| 94 | 92 |
| 95 j_media_player_class_.Reset(GetClass(env, "android/media/MediaPlayer")); | 93 j_media_player_class_.Reset(GetClass(env, "android/media/MediaPlayer")); |
| 96 | 94 |
| 97 jmethodID constructor = GetMethodID(env, | 95 jmethodID constructor = GetMethodID(env, |
| 98 j_media_player_class_, | 96 j_media_player_class_, |
| 99 "<init>", | 97 "<init>", |
| 100 "()V"); | 98 "()V"); |
| 101 ScopedJavaLocalRef<jobject> tmp(env, | 99 ScopedJavaLocalRef<jobject> tmp( |
| 102 env->NewObject(j_media_player_class_.obj(), constructor)); | 100 env, env->NewObject(j_media_player_class_.obj(), constructor)); |
| 103 j_media_player_.Reset(tmp); | 101 j_media_player_.Reset(tmp); |
| 104 | 102 |
| 105 ScopedJavaLocalRef<jobject> j_listener( | |
| 106 listener_.CreateMediaPlayerListener()); | |
| 107 | |
| 108 // Set it as the various listeners. | |
| 109 const char* listeners[] = { | |
| 110 "OnBufferingUpdateListener", | |
| 111 "OnCompletionListener", | |
| 112 "OnErrorListener", | |
| 113 "OnPreparedListener", | |
| 114 "OnSeekCompleteListener", | |
| 115 "OnVideoSizeChangedListener", | |
| 116 }; | |
| 117 for (unsigned int i = 0; i < arraysize(listeners); ++i) { | |
| 118 std::string signature = StringPrintf("(Landroid/media/MediaPlayer$%s;)V", | |
| 119 listeners[i]); | |
| 120 std::string method_name = StringPrintf("set%s", listeners[i]); | |
| 121 jmethodID method = GetMethodID(env, | |
| 122 j_media_player_class_, | |
| 123 method_name.c_str(), | |
| 124 signature.c_str()); | |
| 125 env->CallVoidMethod(j_media_player_.obj(), method, j_listener.obj()); | |
| 126 CheckException(env); | |
| 127 } | |
| 128 | |
| 129 jobject j_context = base::android::GetApplicationContext(); | 103 jobject j_context = base::android::GetApplicationContext(); |
| 130 DCHECK(j_context); | 104 DCHECK(j_context); |
| 131 jmethodID method = GetMethodID(env, j_media_player_class_, | 105 |
| 132 "setWakeMode", "(Landroid/content/Context;I)V"); | 106 listener_.CreateMediaPlayerListener(j_context, j_media_player_.obj()); |
| 133 env->CallVoidMethod(j_media_player_.obj(), method, j_context, | |
| 134 kAndroidFullWakeLock); | |
| 135 CheckException(env); | |
| 136 } | 107 } |
| 137 | 108 |
| 138 void MediaPlayerBridge::SetVideoSurface(jobject surface) { | 109 void MediaPlayerBridge::SetVideoSurface(jobject surface) { |
| 139 if (j_media_player_.is_null() && surface != NULL) | 110 if (j_media_player_.is_null() && surface != NULL) |
| 140 Prepare(); | 111 Prepare(); |
| 141 | 112 |
| 142 JNIEnv* env = AttachCurrentThread(); | 113 JNIEnv* env = AttachCurrentThread(); |
| 143 CHECK(env); | 114 CHECK(env); |
| 144 | 115 |
| 145 jmethodID method = GetMethodID(env, | 116 jmethodID method = GetMethodID(env, |
| (...skipping 18 matching lines...) Expand all Loading... |
| 164 | 135 |
| 165 void MediaPlayerBridge::GetCookiesCallback(const std::string& cookies) { | 136 void MediaPlayerBridge::GetCookiesCallback(const std::string& cookies) { |
| 166 cookies_ = cookies; | 137 cookies_ = cookies; |
| 167 has_cookies_ = true; | 138 has_cookies_ = true; |
| 168 | 139 |
| 169 JNIEnv* env = AttachCurrentThread(); | 140 JNIEnv* env = AttachCurrentThread(); |
| 170 CHECK(env); | 141 CHECK(env); |
| 171 | 142 |
| 172 // Create a Java String for the URL. | 143 // Create a Java String for the URL. |
| 173 ScopedJavaLocalRef<jstring> j_url_string = ConvertUTF8ToJavaString(env, url_); | 144 ScopedJavaLocalRef<jstring> j_url_string = ConvertUTF8ToJavaString(env, url_); |
| 174 | 145 ScopedJavaLocalRef<jstring> j_cookies = ConvertUTF8ToJavaString( |
| 175 // Create the android.net.Uri object. | 146 env, cookies_); |
| 176 ScopedJavaLocalRef<jclass> cls(GetClass(env, "android/net/Uri")); | |
| 177 jmethodID method = GetStaticMethodID(env, cls, | |
| 178 "parse", "(Ljava/lang/String;)Landroid/net/Uri;"); | |
| 179 ScopedJavaLocalRef<jobject> j_uri(env, | |
| 180 env->CallStaticObjectMethod(cls.obj(), method, j_url_string.obj())); | |
| 181 | |
| 182 // Create the java.util.Map. | |
| 183 cls.Reset(GetClass(env, "java/util/HashMap")); | |
| 184 jmethodID constructor = GetMethodID(env, cls, "<init>", "()V"); | |
| 185 ScopedJavaLocalRef<jobject> j_map(env, | |
| 186 env->NewObject(cls.obj(), constructor)); | |
| 187 jmethodID put_method = GetMethodID(env, cls, "put", | |
| 188 "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"); | |
| 189 | |
| 190 // Construct headers that needs to be sent with the url. | |
| 191 HeadersMap headers; | |
| 192 // For incognito mode, we need a header to hide url log. | |
| 193 if (hide_url_log_) | |
| 194 headers.insert(std::make_pair("x-hide-urls-from-log", "true")); | |
| 195 // If cookies are present, add them in the header. | |
| 196 if (!cookies_.empty()) | |
| 197 headers.insert(std::make_pair("Cookie", cookies_)); | |
| 198 | |
| 199 // Fill the Map with the headers. | |
| 200 for (HeadersMap::const_iterator iter = headers.begin(); | |
| 201 iter != headers.end(); ++iter) { | |
| 202 ScopedJavaLocalRef<jstring> key = ConvertUTF8ToJavaString(env, iter->first); | |
| 203 ScopedJavaLocalRef<jstring> value = | |
| 204 ConvertUTF8ToJavaString(env, iter->second); | |
| 205 ScopedJavaLocalRef<jobject> result(env, | |
| 206 env->CallObjectMethod(j_map.obj(), put_method, key.obj(), value.obj())); | |
| 207 } | |
| 208 | 147 |
| 209 jobject j_context = base::android::GetApplicationContext(); | 148 jobject j_context = base::android::GetApplicationContext(); |
| 210 DCHECK(j_context); | 149 DCHECK(j_context); |
| 211 | 150 |
| 212 // Finally- Call the setDataSource method. | 151 if (Java_MediaPlayerBridge_setDataSource( |
| 213 jmethodID set_data_source = | 152 env, j_media_player_.obj(), j_context, j_url_string.obj(), |
| 214 GetMethodID(env, j_media_player_class_, "setDataSource", | 153 j_cookies.obj(), hide_url_log_)) { |
| 215 "(Landroid/content/Context;Landroid/net/Uri;Ljava/util/Map;)V"); | |
| 216 env->CallVoidMethod(j_media_player_.obj(), set_data_source, j_context, | |
| 217 j_uri.obj(), j_map.obj()); | |
| 218 bool is_data_source_set_ = !base::android::ClearException(env); | |
| 219 | |
| 220 if (is_data_source_set_) { | |
| 221 if (manager_) | 154 if (manager_) |
| 222 manager_->RequestMediaResources(this); | 155 manager_->RequestMediaResources(this); |
| 223 CallVoidMethod("prepareAsync"); | 156 CallVoidMethod("prepareAsync"); |
| 224 } else { | 157 } else { |
| 225 media_error_cb_.Run(player_id_, MEDIA_ERROR_UNKNOWN); | 158 media_error_cb_.Run(player_id_, MEDIA_ERROR_UNKNOWN); |
| 226 } | 159 } |
| 227 } | 160 } |
| 228 | 161 |
| 229 void MediaPlayerBridge::Start() { | 162 void MediaPlayerBridge::Start() { |
| 230 if (j_media_player_.is_null()) { | 163 if (j_media_player_.is_null()) { |
| (...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 469 | 402 |
| 470 jmethodID method = GetMethodID(env, | 403 jmethodID method = GetMethodID(env, |
| 471 j_media_player_class_, | 404 j_media_player_class_, |
| 472 method_name.c_str(), | 405 method_name.c_str(), |
| 473 "()I"); | 406 "()I"); |
| 474 jint j_result = env->CallIntMethod(j_media_player_.obj(), method); | 407 jint j_result = env->CallIntMethod(j_media_player_.obj(), method); |
| 475 CheckException(env); | 408 CheckException(env); |
| 476 return j_result; | 409 return j_result; |
| 477 } | 410 } |
| 478 | 411 |
| 412 bool MediaPlayerBridge::RegisterMediaPlayerBridge(JNIEnv* env) { |
| 413 bool ret = RegisterNativesImpl(env); |
| 414 DCHECK(g_MediaPlayerBridge_clazz); |
| 415 return ret; |
| 416 } |
| 417 |
| 479 } // namespace media | 418 } // namespace media |
| OLD | NEW |