blob: dfe106647a2fbcf398e23f302215b8bb88989e4f [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/strings/string16.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 "ui/gl/android/scoped_java_surface.h"
#include "url/gurl.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 |manager|'s
// RequestMediaResources() before decoding the media stream. This allows
// |manager| to track unused resources and free them when needed.
// MediaPlayerBridge also forwards Android MediaPlayer callbacks to
// the |manager| when needed.
MediaPlayerBridge(const GURL& url,
const GURL& site_for_cookies,
const std::string& user_agent,
bool hide_url_log,
Client* client,
bool allow_credentials);
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 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.
GURL 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);
// 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 base::string16& username,
const base::string16& 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();
base::WeakPtr<MediaPlayerBridge> WeakPtrForUIThread();
// Whether the player is prepared for playback.
bool prepared_;
// 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_;
// First party url for cookies.
GURL site_for_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_;
// 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_;
DISALLOW_COPY_AND_ASSIGN(MediaPlayerBridge);
};
} // namespace media
#endif // MEDIA_BASE_ANDROID_MEDIA_PLAYER_BRIDGE_H_