blob: 701299c0a0b2994d4206d8036ce6d4cb67e79045 [file] [log] [blame]
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef MEDIA_BASE_ANDROID_MEDIA_PLAYER_BRIDGE_H_
#define MEDIA_BASE_ANDROID_MEDIA_PLAYER_BRIDGE_H_
#include <jni.h>
#include <stdint.h>
#include <map>
#include <memory>
#include <string>
#include "base/android/scoped_java_ref.h"
#include "base/callback.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "media/base/android/media_player_listener.h"
#include "media/base/media_export.h"
#include "media/base/simple_watch_timer.h"
#include "net/cookies/site_for_cookies.h"
#include "ui/gl/android/scoped_java_surface.h"
#include "url/gurl.h"
#include "url/origin.h"
namespace media {
class MediaResourceGetter;
class MediaUrlInterceptor;
// This class serves as a bridge between the native code and Android MediaPlayer
// Java class. For more information on Android MediaPlayer, check
// http://developer.android.com/reference/android/media/MediaPlayer.html
// The actual Android MediaPlayer instance is created lazily when Start(),
// Pause(), SeekTo() gets called. As a result, media information may not
// be available until one of those operations is performed. After that, we
// will cache those information in case the mediaplayer gets released.
// The class uses the corresponding MediaPlayerBridge Java class to talk to
// the Android MediaPlayer instance.
class MEDIA_EXPORT MediaPlayerBridge {
public:
class Client {
public:
// Returns a pointer to the MediaResourceGetter object.
virtual MediaResourceGetter* GetMediaResourceGetter() = 0;
// Returns a pointer to the MediaUrlInterceptor object or null.
virtual MediaUrlInterceptor* GetMediaUrlInterceptor() = 0;
// Called when media duration is first detected or changes.
virtual void OnMediaDurationChanged(base::TimeDelta duration) = 0;
// Called when playback completed.
virtual void OnPlaybackComplete() = 0;
// Called when error happens.
virtual void OnError(int error) = 0;
// Called when video size has changed.
virtual void OnVideoSizeChanged(int width, int height) = 0;
};
// Error types for MediaErrorCB.
enum MediaErrorType {
MEDIA_ERROR_FORMAT,
MEDIA_ERROR_DECODE,
MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK,
MEDIA_ERROR_INVALID_CODE,
MEDIA_ERROR_SERVER_DIED,
};
// Construct a MediaPlayerBridge object. This object needs to call `client`'s
// GetMediaResourceGetter() before decoding the media stream. This allows
// `client` to track unused resources and free them when needed.
// MediaPlayerBridge also forwards Android MediaPlayer callbacks to
// the `client` when needed.
MediaPlayerBridge(const GURL& url,
const net::SiteForCookies& site_for_cookies,
const url::Origin& top_frame_origin,
const std::string& user_agent,
bool hide_url_log,
Client* client,
bool allow_credentials,
bool is_hls);
MediaPlayerBridge(const MediaPlayerBridge&) = delete;
MediaPlayerBridge& operator=(const MediaPlayerBridge&) = delete;
virtual ~MediaPlayerBridge();
// Initialize this object and extract the metadata from the media.
void Initialize();
// Methods to partially expose the underlying MediaPlayer.
void SetVideoSurface(gl::ScopedJavaSurface surface);
void SetPlaybackRate(double playback_rate);
void Pause();
void SeekTo(base::TimeDelta timestamp);
base::TimeDelta GetCurrentTime();
// Starts media playback.
// The first call to this method will call Prepare() and create the underlying
// MediaPlayer for the first time.
void Start();
// The media URL given to the underlying MediaPlayer.
GURL GetUrl();
// The site whose cookies should be given to the MediaPlayer if needed.
const net::SiteForCookies& GetSiteForCookies();
// Set the player volume, and take effect immediately.
// The volume should be between 0.0 and 1.0.
void SetVolume(double volume);
void OnDidSetDataUriDataSource(
JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj,
jboolean success);
private:
friend class MediaPlayerListener;
friend class MediaPlayerBridgeTest;
// Releases the resources such as the underlying MediaPlayer and
// MediaPlayerListener.
void Release();
base::TimeDelta GetDuration();
void PropagateDuration(base::TimeDelta time);
bool IsPlaying();
// Prepare the player for playback, asynchronously. When succeeds,
// OnMediaPrepared() will be called. Otherwise, OnMediaError() will
// be called with an error type.
void Prepare();
// MediaPlayerListener callbacks.
void OnVideoSizeChanged(int width, int height);
void OnMediaError(int error_type);
void OnPlaybackComplete();
void OnMediaPrepared();
// Create the corresponding Java class instance.
void CreateJavaMediaPlayerBridge();
// Get allowed operations from the player.
base::android::ScopedJavaLocalRef<jobject> GetAllowedOperations();
// 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(const base::android::JavaRef<jobject>& j_media_player);
void DetachListener();
// Set the data source for the media player.
void SetDataSource(const std::string& url);
void SetDataSourceInternal();
// Functions that implements media player control.
void StartInternal();
void PauseInternal();
// Calls Java MediaPlayerBridge's seekTo method, or no-ops if the operation
// is not allowed (based off of `can_seek_forward_` and `can_seek_backward_`).
void SeekInternal(base::TimeDelta time);
// Update allowed operations from the player.
void UpdateAllowedOperations();
// Callback function passed to `resource_getter_`. Called when the cookies
// are retrieved.
void OnCookiesRetrieved(const std::string& cookies);
// Callback function passed to `resource_getter_`. Called when the auth
// credentials are retrieved.
void OnAuthCredentialsRetrieved(const std::u16string& username,
const std::u16string& password);
// Extract the media metadata from a url, asynchronously.
// OnMediaMetadataExtracted() will be called when this call finishes.
void ExtractMediaMetadata(const std::string& url);
void OnMediaMetadataExtracted(base::TimeDelta duration,
int width,
int height,
bool success);
// Returns true if a MediaUrlInterceptor registered by the embedder has
// intercepted the url.
bool InterceptMediaUrl(const std::string& url,
int* fd,
int64_t* offset,
int64_t* size);
// Sets the underlying MediaPlayer's volume.
void UpdateVolumeInternal();
void OnWatchTimerTick();
base::WeakPtr<MediaPlayerBridge> WeakPtrForUIThread();
// Whether the player is prepared for playback.
bool prepared_;
// Whether the player completed playback.
bool playback_completed_;
// Pending play event while player is preparing.
bool pending_play_;
// Pending seek time while player is preparing.
base::TimeDelta pending_seek_;
// Whether a seek should be performed after preparing.
bool should_seek_on_prepare_;
// Url for playback.
GURL url_;
// Used to determine if cookies are accessed in a third-party context.
net::SiteForCookies site_for_cookies_;
// Used to check for cookie content settings.
url::Origin top_frame_origin_;
// Waiting to retrieve cookies for `url_`.
bool pending_retrieve_cookies_;
// Whether to prepare after cookies retrieved.
bool should_prepare_on_retrieved_cookies_;
// User agent string to be used for media player.
const std::string user_agent_;
// Hide url log from media player.
bool hide_url_log_;
// Stats about the media.
base::TimeDelta duration_;
int width_;
int height_;
bool can_seek_forward_;
bool can_seek_backward_;
// The player volume. Should be between 0.0 and 1.0.
double volume_;
// Cookies for `url_`.
std::string cookies_;
// The surface object currently owned by the player.
gl::ScopedJavaSurface surface_;
// Java MediaPlayerBridge instance.
base::android::ScopedJavaGlobalRef<jobject> j_media_player_bridge_;
// Whether user credentials are allowed to be passed.
bool allow_credentials_;
// Whether the preparation for playback or the playback is currently going on.
// This flag is set in Start() and cleared in Pause() and Release(). Used for
// UMA reporting only.
bool is_active_;
// Whether there has been any errors in the active state.
bool has_error_;
// The flag is set if Start() has been called at least once.
bool has_ever_started_;
// State for watch time reporting.
bool is_hls_;
SimpleWatchTimer watch_timer_;
// A reference to the owner of `this`.
Client* client_;
// Listener object that listens to all the media player events.
std::unique_ptr<MediaPlayerListener> listener_;
// Weak pointer passed to `listener_` for callbacks.
// NOTE: Weak pointers must be invalidated before all other member variables.
base::WeakPtrFactory<MediaPlayerBridge> weak_factory_{this};
};
} // namespace media
#endif // MEDIA_BASE_ANDROID_MEDIA_PLAYER_BRIDGE_H_