Commit 68c2a866 authored by qinmin's avatar qinmin Committed by Commit bot

Listen to the audio focus event for MSE/EME

For MSE/EME, we never listen to the audio focus change.
That will cause the video to continue playing when another app plays sound.
Attach MediaPlayerListener to the MediaSourcePlayer should fix the issue.

BUG=421861

Review URL: https://codereview.chromium.org/643353002

Cr-Commit-Position: refs/heads/master@{#299819}
parent db571578
......@@ -125,12 +125,14 @@ class MediaPlayerListener implements MediaPlayer.OnPreparedListener,
Context context, MediaPlayerBridge mediaPlayerBridge) {
final MediaPlayerListener listener =
new MediaPlayerListener(nativeMediaPlayerListener, context);
mediaPlayerBridge.setOnBufferingUpdateListener(listener);
mediaPlayerBridge.setOnCompletionListener(listener);
mediaPlayerBridge.setOnErrorListener(listener);
mediaPlayerBridge.setOnPreparedListener(listener);
mediaPlayerBridge.setOnSeekCompleteListener(listener);
mediaPlayerBridge.setOnVideoSizeChangedListener(listener);
if (mediaPlayerBridge != null) {
mediaPlayerBridge.setOnBufferingUpdateListener(listener);
mediaPlayerBridge.setOnCompletionListener(listener);
mediaPlayerBridge.setOnErrorListener(listener);
mediaPlayerBridge.setOnPreparedListener(listener);
mediaPlayerBridge.setOnSeekCompleteListener(listener);
mediaPlayerBridge.setOnVideoSizeChangedListener(listener);
}
AudioManager am = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
am.requestAudioFocus(
......
......@@ -4,7 +4,9 @@
#include "media/base/android/media_player_android.h"
#include "base/android/jni_android.h"
#include "base/logging.h"
#include "base/message_loop/message_loop_proxy.h"
#include "media/base/android/media_drm_bridge.h"
#include "media/base/android/media_player_manager.h"
......@@ -18,7 +20,10 @@ MediaPlayerAndroid::MediaPlayerAndroid(
: request_media_resources_cb_(request_media_resources_cb),
player_id_(player_id),
manager_(manager),
frame_url_(frame_url) {
frame_url_(frame_url),
weak_factory_(this) {
listener_.reset(new MediaPlayerListener(base::MessageLoopProxy::current(),
weak_factory_.GetWeakPtr()));
}
MediaPlayerAndroid::~MediaPlayerAndroid() {}
......@@ -37,4 +42,42 @@ void MediaPlayerAndroid::SetCdm(BrowserCdm* /* cdm */) {
return;
}
void MediaPlayerAndroid::OnVideoSizeChanged(int width, int height) {
manager_->OnVideoSizeChanged(player_id(), width, height);
}
void MediaPlayerAndroid::OnMediaError(int error_type) {
manager_->OnError(player_id(), error_type);
}
void MediaPlayerAndroid::OnBufferingUpdate(int percent) {
manager_->OnBufferingUpdate(player_id(), percent);
}
void MediaPlayerAndroid::OnPlaybackComplete() {
manager_->OnPlaybackComplete(player_id());
}
void MediaPlayerAndroid::OnMediaInterrupted() {
manager_->OnMediaInterrupted(player_id());
}
void MediaPlayerAndroid::OnSeekComplete() {
manager_->OnSeekComplete(player_id(), GetCurrentTime());
}
void MediaPlayerAndroid::OnMediaPrepared() {}
void MediaPlayerAndroid::AttachListener(jobject j_media_player) {
jobject j_context = base::android::GetApplicationContext();
DCHECK(j_context);
listener_->CreateMediaPlayerListener(j_context, j_media_player);
}
void MediaPlayerAndroid::DetachListener() {
listener_->ReleaseMediaPlayerListenerResources();
}
} // namespace media
......@@ -9,7 +9,9 @@
#include <string>
#include "base/callback.h"
#include "base/memory/weak_ptr.h"
#include "base/time/time.h"
#include "media/base/android/media_player_listener.h"
#include "media/base/media_export.h"
#include "ui/gl/android/scoped_java_surface.h"
#include "url/gurl.h"
......@@ -83,11 +85,31 @@ class MEDIA_EXPORT MediaPlayerAndroid {
const RequestMediaResourcesCB& request_media_resources_cb,
const GURL& frame_url);
// TODO(qinmin): Simplify the MediaPlayerListener class to only listen to
// media interrupt events. And have a separate child class to listen to all
// the events needed by MediaPlayerBridge. http://crbug.com/422597.
// MediaPlayerListener callbacks.
virtual void OnVideoSizeChanged(int width, int height);
virtual void OnMediaError(int error_type);
virtual void OnBufferingUpdate(int percent);
virtual void OnPlaybackComplete();
virtual void OnMediaInterrupted();
virtual void OnSeekComplete();
virtual void OnMediaPrepared();
// Attach/Detaches |listener_| for listening to all the media events. If
// |j_media_player| is NULL, |listener_| only listens to the system media
// events. Otherwise, it also listens to the events from |j_media_player|.
void AttachListener(jobject j_media_player);
void DetachListener();
MediaPlayerManager* manager() { return manager_; }
RequestMediaResourcesCB request_media_resources_cb_;
private:
friend class MediaPlayerListener;
// Player ID assigned to this player.
int player_id_;
......@@ -97,6 +119,13 @@ class MEDIA_EXPORT MediaPlayerAndroid {
// Url for the frame that contains this player.
GURL frame_url_;
// Listener object that listens to all the media player events.
scoped_ptr<MediaPlayerListener> listener_;
// Weak pointer passed to |listener_| for callbacks.
// NOTE: Weak pointers must be invalidated before all other member variables.
base::WeakPtrFactory<MediaPlayerAndroid> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(MediaPlayerAndroid);
};
......
......@@ -50,8 +50,6 @@ MediaPlayerBridge::MediaPlayerBridge(
volume_(-1.0),
allow_credentials_(allow_credentials),
weak_factory_(this) {
listener_.reset(new MediaPlayerListener(base::MessageLoopProxy::current(),
weak_factory_.GetWeakPtr()));
}
MediaPlayerBridge::~MediaPlayerBridge() {
......@@ -103,7 +101,7 @@ void MediaPlayerBridge::CreateJavaMediaPlayerBridge() {
if (volume_ >= 0)
SetVolume(volume_);
SetMediaPlayerListener();
AttachListener(j_media_player_bridge_.obj());
}
void MediaPlayerBridge::SetJavaMediaPlayerBridge(
......@@ -121,13 +119,6 @@ base::android::ScopedJavaLocalRef<jobject> MediaPlayerBridge::
return j_bridge;
}
void MediaPlayerBridge::SetMediaPlayerListener() {
jobject j_context = base::android::GetApplicationContext();
DCHECK(j_context);
listener_->CreateMediaPlayerListener(j_context, j_media_player_bridge_.obj());
}
void MediaPlayerBridge::SetDuration(base::TimeDelta duration) {
duration_ = duration;
}
......@@ -386,7 +377,7 @@ void MediaPlayerBridge::Release() {
JNIEnv* env = base::android::AttachCurrentThread();
Java_MediaPlayerBridge_release(env, j_media_player_bridge_.obj());
j_media_player_bridge_.Reset();
listener_->ReleaseMediaPlayerListenerResources();
DetachListener();
}
void MediaPlayerBridge::SetVolume(double volume) {
......@@ -404,29 +395,17 @@ void MediaPlayerBridge::SetVolume(double volume) {
void MediaPlayerBridge::OnVideoSizeChanged(int width, int height) {
width_ = width;
height_ = height;
manager()->OnVideoSizeChanged(player_id(), width, height);
}
void MediaPlayerBridge::OnMediaError(int error_type) {
manager()->OnError(player_id(), error_type);
}
void MediaPlayerBridge::OnBufferingUpdate(int percent) {
manager()->OnBufferingUpdate(player_id(), percent);
MediaPlayerAndroid::OnVideoSizeChanged(width, height);
}
void MediaPlayerBridge::OnPlaybackComplete() {
time_update_timer_.Stop();
manager()->OnPlaybackComplete(player_id());
MediaPlayerAndroid::OnPlaybackComplete();
}
void MediaPlayerBridge::OnMediaInterrupted() {
time_update_timer_.Stop();
manager()->OnMediaInterrupted(player_id());
}
void MediaPlayerBridge::OnSeekComplete() {
manager()->OnSeekComplete(player_id(), GetCurrentTime());
MediaPlayerAndroid::OnMediaInterrupted();
}
void MediaPlayerBridge::OnMediaPrepared() {
......
......@@ -17,7 +17,6 @@
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "media/base/android/media_player_android.h"
#include "media/base/android/media_player_listener.h"
#include "url/gurl.h"
namespace media {
......@@ -75,19 +74,11 @@ class MEDIA_EXPORT MediaPlayerBridge : public MediaPlayerAndroid {
virtual GURL GetUrl() override;
virtual GURL GetFirstPartyForCookies() override;
// MediaPlayerListener callbacks.
void OnVideoSizeChanged(int width, int height);
void OnMediaError(int error_type);
void OnBufferingUpdate(int percent);
void OnPlaybackComplete();
void OnMediaInterrupted();
void OnSeekComplete();
void OnDidSetDataUriDataSource(JNIEnv* env, jobject obj, jboolean success);
protected:
void SetJavaMediaPlayerBridge(jobject j_media_player_bridge);
base::android::ScopedJavaLocalRef<jobject> GetJavaMediaPlayerBridge();
void SetMediaPlayerListener();
void SetDuration(base::TimeDelta time);
virtual void PendingSeekInternal(const base::TimeDelta& time);
......@@ -96,7 +87,12 @@ class MEDIA_EXPORT MediaPlayerBridge : public MediaPlayerAndroid {
// OnMediaPrepared() will be called. Otherwise, OnMediaError() will
// be called with an error type.
virtual void Prepare();
void OnMediaPrepared();
// MediaPlayerAndroid implementation.
virtual void OnVideoSizeChanged(int width, int height) override;
virtual void OnPlaybackComplete() override;
virtual void OnMediaInterrupted() override;
virtual void OnMediaPrepared() override;
// Create the corresponding Java class instance.
virtual void CreateJavaMediaPlayerBridge();
......@@ -105,8 +101,6 @@ class MEDIA_EXPORT MediaPlayerBridge : public MediaPlayerAndroid {
virtual base::android::ScopedJavaLocalRef<jobject> GetAllowedOperations();
private:
friend class MediaPlayerListener;
// Set the data source for the media player.
void SetDataSource(const std::string& url);
......@@ -180,16 +174,12 @@ class MEDIA_EXPORT MediaPlayerBridge : public MediaPlayerAndroid {
base::RepeatingTimer<MediaPlayerBridge> time_update_timer_;
// Listener object that listens to all the media player events.
scoped_ptr<MediaPlayerListener> listener_;
// Volume of playback.
double volume_;
// Whether user credentials are allowed to be passed.
bool allow_credentials_;
// Weak pointer passed to |listener_| for callbacks.
// NOTE: Weak pointers must be invalidated before all other member variables.
base::WeakPtrFactory<MediaPlayerBridge> weak_factory_;
......
......@@ -6,13 +6,11 @@
#include "base/android/jni_android.h"
#include "base/bind.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/single_thread_task_runner.h"
#include "media/base/android/media_player_bridge.h"
// Auto generated jni class from MediaPlayerListener.java.
// Check base/android/jni_generator/golden_sample_for_tests_jni.h for example.
#include "jni/MediaPlayerListener_jni.h"
#include "media/base/android/media_player_android.h"
using base::android::AttachCurrentThread;
using base::android::CheckException;
......@@ -22,7 +20,7 @@ namespace media {
MediaPlayerListener::MediaPlayerListener(
const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
base::WeakPtr<MediaPlayerBridge> media_player)
base::WeakPtr<MediaPlayerAndroid> media_player)
: task_runner_(task_runner),
media_player_(media_player) {
DCHECK(task_runner_.get());
......@@ -32,12 +30,13 @@ MediaPlayerListener::MediaPlayerListener(
MediaPlayerListener::~MediaPlayerListener() {}
void MediaPlayerListener::CreateMediaPlayerListener(
jobject context, jobject media_player_bridge) {
jobject context, jobject media_player) {
JNIEnv* env = AttachCurrentThread();
CHECK(env);
j_media_player_listener_.Reset(
Java_MediaPlayerListener_create(
env, reinterpret_cast<intptr_t>(this), context, media_player_bridge));
if (j_media_player_listener_.is_null()) {
j_media_player_listener_.Reset(Java_MediaPlayerListener_create(
env, reinterpret_cast<intptr_t>(this), context, media_player));
}
}
......@@ -54,44 +53,44 @@ void MediaPlayerListener::ReleaseMediaPlayerListenerResources() {
void MediaPlayerListener::OnMediaError(
JNIEnv* /* env */, jobject /* obj */, jint error_type) {
task_runner_->PostTask(FROM_HERE, base::Bind(
&MediaPlayerBridge::OnMediaError, media_player_, error_type));
&MediaPlayerAndroid::OnMediaError, media_player_, error_type));
}
void MediaPlayerListener::OnVideoSizeChanged(
JNIEnv* /* env */, jobject /* obj */, jint width, jint height) {
task_runner_->PostTask(FROM_HERE, base::Bind(
&MediaPlayerBridge::OnVideoSizeChanged, media_player_,
&MediaPlayerAndroid::OnVideoSizeChanged, media_player_,
width, height));
}
void MediaPlayerListener::OnBufferingUpdate(
JNIEnv* /* env */, jobject /* obj */, jint percent) {
task_runner_->PostTask(FROM_HERE, base::Bind(
&MediaPlayerBridge::OnBufferingUpdate, media_player_, percent));
&MediaPlayerAndroid::OnBufferingUpdate, media_player_, percent));
}
void MediaPlayerListener::OnPlaybackComplete(
JNIEnv* /* env */, jobject /* obj */) {
task_runner_->PostTask(FROM_HERE, base::Bind(
&MediaPlayerBridge::OnPlaybackComplete, media_player_));
&MediaPlayerAndroid::OnPlaybackComplete, media_player_));
}
void MediaPlayerListener::OnSeekComplete(
JNIEnv* /* env */, jobject /* obj */) {
task_runner_->PostTask(FROM_HERE, base::Bind(
&MediaPlayerBridge::OnSeekComplete, media_player_));
&MediaPlayerAndroid::OnSeekComplete, media_player_));
}
void MediaPlayerListener::OnMediaPrepared(
JNIEnv* /* env */, jobject /* obj */) {
task_runner_->PostTask(FROM_HERE, base::Bind(
&MediaPlayerBridge::OnMediaPrepared, media_player_));
&MediaPlayerAndroid::OnMediaPrepared, media_player_));
}
void MediaPlayerListener::OnMediaInterrupted(
JNIEnv* /* env */, jobject /* obj */) {
task_runner_->PostTask(FROM_HERE, base::Bind(
&MediaPlayerBridge::OnMediaInterrupted, media_player_));
&MediaPlayerAndroid::OnMediaInterrupted, media_player_));
}
bool MediaPlayerListener::RegisterMediaPlayerListener(JNIEnv* env) {
......
......@@ -17,10 +17,10 @@ class SingleThreadTaskRunner;
namespace media {
class MediaPlayerBridge;
class MediaPlayerAndroid;
// Acts as a thread proxy between java MediaPlayerListener object and
// MediaPlayerBridge so that callbacks are posted onto the UI thread.
// MediaPlayerAndroid so that callbacks are posted onto the UI thread.
class MediaPlayerListener {
public:
// Construct a native MediaPlayerListener object. Callbacks from the java
......@@ -28,7 +28,7 @@ class MediaPlayerListener {
// |task_runner|.
MediaPlayerListener(
const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
base::WeakPtr<MediaPlayerBridge> media_player);
base::WeakPtr<MediaPlayerAndroid> media_player);
virtual ~MediaPlayerListener();
// Called by the Java MediaPlayerListener and mirrored to corresponding
......@@ -42,8 +42,10 @@ class MediaPlayerListener {
void OnMediaPrepared(JNIEnv* /* env */, jobject /* obj */);
void OnMediaInterrupted(JNIEnv* /* env */, jobject /* obj */);
// Create a Java MediaPlayerListener object.
void CreateMediaPlayerListener(jobject context, jobject media_player_bridge);
// Create a Java MediaPlayerListener object and listens to all the media
// related events from system and |media_player|. If |media_player| is NULL,
// this class only listens to system events.
void CreateMediaPlayerListener(jobject context, jobject media_player);
void ReleaseMediaPlayerListenerResources();
// Register MediaPlayerListener in the system library loader.
......@@ -53,8 +55,8 @@ class MediaPlayerListener {
// The message loop where |media_player_| lives.
scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
// The MediaPlayerBridge object all the callbacks should be send to.
base::WeakPtr<MediaPlayerBridge> media_player_;
// The MediaPlayerAndroid object all the callbacks should be sent to.
base::WeakPtr<MediaPlayerAndroid> media_player_;
base::android::ScopedJavaGlobalRef<jobject> j_media_player_listener_;
......
......@@ -194,6 +194,7 @@ void MediaSourcePlayer::Release() {
playing_ = false;
decoder_starvation_callback_.Cancel();
DetachListener();
}
void MediaSourcePlayer::SetVolume(double volume) {
......@@ -226,6 +227,7 @@ void MediaSourcePlayer::StartInternal() {
// be clear (not encrypted) or encrypted with different keys. So
// |is_waiting_for_key_| condition may not be true anymore.
is_waiting_for_key_ = false;
AttachListener(NULL);
SetPendingEvent(PREFETCH_REQUEST_EVENT_PENDING);
ProcessPendingEvents();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment