| Index: webkit/renderer/media/android/webmediaplayer_android.cc
|
| diff --git a/webkit/renderer/media/android/webmediaplayer_android.cc b/webkit/renderer/media/android/webmediaplayer_android.cc
|
| deleted file mode 100644
|
| index 31e9fa4be69a0c7b81bd18fca0bf998afa197741..0000000000000000000000000000000000000000
|
| --- a/webkit/renderer/media/android/webmediaplayer_android.cc
|
| +++ /dev/null
|
| @@ -1,1113 +0,0 @@
|
| -// Copyright 2013 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.
|
| -
|
| -#include "webkit/renderer/media/android/webmediaplayer_android.h"
|
| -
|
| -#include "base/bind.h"
|
| -#include "base/command_line.h"
|
| -#include "base/files/file_path.h"
|
| -#include "base/logging.h"
|
| -#include "base/metrics/histogram.h"
|
| -#include "base/strings/string_number_conversions.h"
|
| -#include "cc/layers/video_layer.h"
|
| -#include "gpu/GLES2/gl2extchromium.h"
|
| -#include "media/base/android/media_player_android.h"
|
| -#include "media/base/bind_to_loop.h"
|
| -#include "media/base/media_switches.h"
|
| -#include "media/base/video_frame.h"
|
| -#include "net/base/mime_util.h"
|
| -#include "third_party/WebKit/public/platform/WebString.h"
|
| -#include "third_party/WebKit/public/web/WebDocument.h"
|
| -#include "third_party/WebKit/public/web/WebFrame.h"
|
| -#include "third_party/WebKit/public/web/WebMediaPlayerClient.h"
|
| -#include "third_party/WebKit/public/web/WebMediaSource.h"
|
| -#include "third_party/WebKit/public/web/WebRuntimeFeatures.h"
|
| -#include "third_party/WebKit/public/web/WebView.h"
|
| -#include "webkit/renderer/compositor_bindings/web_layer_impl.h"
|
| -#include "webkit/renderer/media/android/webmediaplayer_manager_android.h"
|
| -#include "webkit/renderer/media/android/webmediaplayer_proxy_android.h"
|
| -#include "webkit/renderer/media/crypto/key_systems.h"
|
| -#include "webkit/renderer/media/webmediaplayer_delegate.h"
|
| -#include "webkit/renderer/media/webmediaplayer_util.h"
|
| -
|
| -#if defined(GOOGLE_TV)
|
| -#include "webkit/renderer/media/media_stream_audio_renderer.h"
|
| -#include "webkit/renderer/media/media_stream_client.h"
|
| -#endif
|
| -
|
| -static const uint32 kGLTextureExternalOES = 0x8D65;
|
| -
|
| -using WebKit::WebMediaPlayer;
|
| -using WebKit::WebMediaSource;
|
| -using WebKit::WebSize;
|
| -using WebKit::WebString;
|
| -using WebKit::WebTimeRanges;
|
| -using WebKit::WebURL;
|
| -using media::MediaPlayerAndroid;
|
| -using media::VideoFrame;
|
| -
|
| -namespace {
|
| -// Prefix for histograms related to Encrypted Media Extensions.
|
| -const char* kMediaEme = "Media.EME.";
|
| -} // namespace
|
| -
|
| -namespace webkit_media {
|
| -
|
| -#define BIND_TO_RENDER_LOOP(function) \
|
| - media::BindToLoop(main_loop_, base::Bind(function, AsWeakPtr()))
|
| -
|
| -WebMediaPlayerAndroid::WebMediaPlayerAndroid(
|
| - WebKit::WebFrame* frame,
|
| - WebKit::WebMediaPlayerClient* client,
|
| - base::WeakPtr<WebMediaPlayerDelegate> delegate,
|
| - WebMediaPlayerManagerAndroid* manager,
|
| - WebMediaPlayerProxyAndroid* proxy,
|
| - StreamTextureFactory* factory,
|
| - media::MediaLog* media_log)
|
| - : frame_(frame),
|
| - client_(client),
|
| - delegate_(delegate),
|
| - buffered_(1u),
|
| - main_loop_(base::MessageLoopProxy::current()),
|
| - ignore_metadata_duration_change_(false),
|
| - pending_seek_(0),
|
| - seeking_(false),
|
| - did_loading_progress_(false),
|
| - manager_(manager),
|
| - network_state_(WebMediaPlayer::NetworkStateEmpty),
|
| - ready_state_(WebMediaPlayer::ReadyStateHaveNothing),
|
| - is_playing_(false),
|
| - needs_establish_peer_(true),
|
| - stream_texture_proxy_initialized_(false),
|
| - has_size_info_(false),
|
| - has_media_metadata_(false),
|
| - has_media_info_(false),
|
| - stream_texture_factory_(factory),
|
| - needs_external_surface_(false),
|
| - video_frame_provider_client_(NULL),
|
| -#if defined(GOOGLE_TV)
|
| - demuxer_(NULL),
|
| -#endif // defined(GOOGLE_TV)
|
| - source_type_(MediaPlayerAndroid::SOURCE_TYPE_URL),
|
| - proxy_(proxy),
|
| - current_time_(0),
|
| - media_log_(media_log),
|
| - media_stream_client_(NULL) {
|
| - DCHECK(proxy_);
|
| - DCHECK(manager_);
|
| -
|
| - // We want to be notified of |main_loop_| destruction.
|
| - base::MessageLoop::current()->AddDestructionObserver(this);
|
| -
|
| - player_id_ = manager_->RegisterMediaPlayer(this);
|
| -
|
| - if (stream_texture_factory_) {
|
| - stream_texture_proxy_.reset(stream_texture_factory_->CreateProxy());
|
| - stream_id_ = stream_texture_factory_->CreateStreamTexture(&texture_id_);
|
| - ReallocateVideoFrame();
|
| - }
|
| -
|
| - if (WebKit::WebRuntimeFeatures::isLegacyEncryptedMediaEnabled()) {
|
| - // |decryptor_| is owned, so Unretained() is safe here.
|
| - decryptor_.reset(new ProxyDecryptor(
|
| -#if defined(ENABLE_PEPPER_CDMS)
|
| - client,
|
| - frame,
|
| -#endif // defined(ENABLE_PEPPER_CDMS)
|
| -#if defined(OS_ANDROID) && !defined(GOOGLE_TV)
|
| - proxy_,
|
| - player_id_, // TODO(xhwang): Use media_keys_id when MediaKeys are
|
| - // separated from WebMediaPlayer.
|
| -#endif // defined(OS_ANDROID) && !defined(GOOGLE_TV)
|
| - base::Bind(&WebMediaPlayerAndroid::OnKeyAdded, base::Unretained(this)),
|
| - base::Bind(&WebMediaPlayerAndroid::OnKeyError, base::Unretained(this)),
|
| - base::Bind(&WebMediaPlayerAndroid::OnKeyMessage,
|
| - base::Unretained(this))));
|
| - }
|
| -}
|
| -
|
| -WebMediaPlayerAndroid::~WebMediaPlayerAndroid() {
|
| - SetVideoFrameProviderClient(NULL);
|
| - client_->setWebLayer(NULL);
|
| -
|
| - if (proxy_)
|
| - proxy_->DestroyPlayer(player_id_);
|
| -
|
| - if (stream_id_)
|
| - stream_texture_factory_->DestroyStreamTexture(texture_id_);
|
| -
|
| - if (manager_)
|
| - manager_->UnregisterMediaPlayer(player_id_);
|
| -
|
| - if (base::MessageLoop::current())
|
| - base::MessageLoop::current()->RemoveDestructionObserver(this);
|
| -
|
| - if (source_type_ == MediaPlayerAndroid::SOURCE_TYPE_MSE && delegate_)
|
| - delegate_->PlayerGone(this);
|
| -
|
| -#if defined(GOOGLE_TV)
|
| - if (audio_renderer_) {
|
| - if (audio_renderer_->IsLocalRenderer()) {
|
| - audio_renderer_->Stop();
|
| - } else if (!paused()) {
|
| - // The |audio_renderer_| can be shared by multiple remote streams, and
|
| - // it will be stopped when WebRtcAudioDeviceImpl goes away. So we simply
|
| - // pause the |audio_renderer_| here to avoid re-creating the
|
| - // |audio_renderer_|.
|
| - audio_renderer_->Pause();
|
| - }
|
| - }
|
| - if (demuxer_ && !destroy_demuxer_cb_.is_null()) {
|
| - media_source_delegate_.reset();
|
| - destroy_demuxer_cb_.Run();
|
| - }
|
| -#endif
|
| -}
|
| -
|
| -void WebMediaPlayerAndroid::load(const WebURL& url, CORSMode cors_mode) {
|
| - load(url, NULL, cors_mode);
|
| -}
|
| -
|
| -void WebMediaPlayerAndroid::load(const WebURL& url,
|
| - WebMediaSource* media_source,
|
| - CORSMode cors_mode) {
|
| - source_type_ = MediaPlayerAndroid::SOURCE_TYPE_URL;
|
| - has_media_metadata_ = false;
|
| - has_media_info_ = false;
|
| -
|
| - if (media_source)
|
| - source_type_ = MediaPlayerAndroid::SOURCE_TYPE_MSE;
|
| -#if defined(GOOGLE_TV)
|
| - if (media_stream_client_) {
|
| - DCHECK(!media_source);
|
| - source_type_ = MediaPlayerAndroid::SOURCE_TYPE_STREAM;
|
| - }
|
| -#endif
|
| -
|
| - if (source_type_ != MediaPlayerAndroid::SOURCE_TYPE_URL) {
|
| - has_media_info_ = true;
|
| - media_source_delegate_.reset(
|
| - new MediaSourceDelegate(proxy_, player_id_, media_log_));
|
| - // |media_source_delegate_| is owned, so Unretained() is safe here.
|
| - if (source_type_ == MediaPlayerAndroid::SOURCE_TYPE_MSE) {
|
| - media_source_delegate_->InitializeMediaSource(
|
| - media_source,
|
| - base::Bind(&WebMediaPlayerAndroid::OnNeedKey, base::Unretained(this)),
|
| - base::Bind(&WebMediaPlayerAndroid::UpdateNetworkState,
|
| - base::Unretained(this)),
|
| - BIND_TO_RENDER_LOOP(&WebMediaPlayerAndroid::OnDurationChange));
|
| - }
|
| -#if defined(GOOGLE_TV)
|
| - if (source_type_ == MediaPlayerAndroid::SOURCE_TYPE_STREAM) {
|
| - media_source_delegate_->InitializeMediaStream(
|
| - demuxer_,
|
| - base::Bind(&WebMediaPlayerAndroid::UpdateNetworkState,
|
| - base::Unretained(this)));
|
| - audio_renderer_ = media_stream_client_->GetAudioRenderer(url);
|
| - if (audio_renderer_)
|
| - audio_renderer_->Start();
|
| - }
|
| -#endif
|
| - } else {
|
| - info_loader_.reset(
|
| - new MediaInfoLoader(
|
| - url,
|
| - cors_mode,
|
| - base::Bind(&WebMediaPlayerAndroid::DidLoadMediaInfo,
|
| - base::Unretained(this))));
|
| - info_loader_->Start(frame_);
|
| - }
|
| -
|
| - InitializeMediaPlayer(url);
|
| -}
|
| -
|
| -void WebMediaPlayerAndroid::InitializeMediaPlayer(const WebURL& url) {
|
| - url_ = url;
|
| - GURL first_party_url = frame_->document().firstPartyForCookies();
|
| - proxy_->Initialize(player_id_, url, source_type_, first_party_url);
|
| - if (manager_->IsInFullscreen(frame_))
|
| - proxy_->EnterFullscreen(player_id_);
|
| -
|
| - UpdateNetworkState(WebMediaPlayer::NetworkStateLoading);
|
| - UpdateReadyState(WebMediaPlayer::ReadyStateHaveNothing);
|
| -}
|
| -
|
| -void WebMediaPlayerAndroid::DidLoadMediaInfo(
|
| - MediaInfoLoader::Status status) {
|
| - DCHECK(!media_source_delegate_);
|
| - if (status == MediaInfoLoader::kFailed) {
|
| - info_loader_.reset();
|
| - UpdateNetworkState(WebMediaPlayer::NetworkStateNetworkError);
|
| - return;
|
| - }
|
| -
|
| - has_media_info_ = true;
|
| - if (has_media_metadata_ &&
|
| - ready_state_ != WebMediaPlayer::ReadyStateHaveEnoughData) {
|
| - UpdateReadyState(WebMediaPlayer::ReadyStateHaveMetadata);
|
| - UpdateReadyState(WebMediaPlayer::ReadyStateHaveEnoughData);
|
| - }
|
| -}
|
| -
|
| -void WebMediaPlayerAndroid::play() {
|
| -#if defined(GOOGLE_TV)
|
| - if (hasVideo() && needs_external_surface_) {
|
| - DCHECK(!needs_establish_peer_);
|
| - proxy_->RequestExternalSurface(player_id_, last_computed_rect_);
|
| - }
|
| - if (audio_renderer_ && paused())
|
| - audio_renderer_->Play();
|
| -#endif
|
| - if (hasVideo() && needs_establish_peer_)
|
| - EstablishSurfaceTexturePeer();
|
| -
|
| - if (paused())
|
| - proxy_->Start(player_id_);
|
| - UpdatePlayingState(true);
|
| -}
|
| -
|
| -void WebMediaPlayerAndroid::pause() {
|
| -#if defined(GOOGLE_TV)
|
| - if (audio_renderer_ && !paused())
|
| - audio_renderer_->Pause();
|
| -#endif
|
| - proxy_->Pause(player_id_);
|
| - UpdatePlayingState(false);
|
| -}
|
| -
|
| -void WebMediaPlayerAndroid::seek(double seconds) {
|
| - pending_seek_ = seconds;
|
| - if (seeking_ && media_source_delegate_)
|
| - media_source_delegate_->CancelPendingSeek();
|
| - seeking_ = true;
|
| -
|
| - base::TimeDelta seek_time = ConvertSecondsToTimestamp(seconds);
|
| -#if defined(GOOGLE_TV)
|
| - // TODO(qinmin): check if GTV can also defer the seek until the browser side
|
| - // player is ready.
|
| - if (media_source_delegate_)
|
| - media_source_delegate_->Seek(seek_time);
|
| -#endif
|
| - proxy_->Seek(player_id_, seek_time);
|
| -}
|
| -
|
| -bool WebMediaPlayerAndroid::supportsFullscreen() const {
|
| - return true;
|
| -}
|
| -
|
| -bool WebMediaPlayerAndroid::supportsSave() const {
|
| - return false;
|
| -}
|
| -
|
| -void WebMediaPlayerAndroid::setRate(double rate) {
|
| - NOTIMPLEMENTED();
|
| -}
|
| -
|
| -void WebMediaPlayerAndroid::setVolume(double volume) {
|
| - NOTIMPLEMENTED();
|
| -}
|
| -
|
| -bool WebMediaPlayerAndroid::hasVideo() const {
|
| - // If we have obtained video size information before, use it.
|
| - if (has_size_info_)
|
| - return !natural_size_.isEmpty();
|
| -
|
| - // TODO(qinmin): need a better method to determine whether the current media
|
| - // content contains video. Android does not provide any function to do
|
| - // this.
|
| - // We don't know whether the current media content has video unless
|
| - // the player is prepared. If the player is not prepared, we fall back
|
| - // to the mime-type. There may be no mime-type on a redirect URL.
|
| - // In that case, we conservatively assume it contains video so that
|
| - // enterfullscreen call will not fail.
|
| - if (!url_.has_path())
|
| - return false;
|
| - std::string mime;
|
| - if(!net::GetMimeTypeFromFile(base::FilePath(url_.path()), &mime))
|
| - return true;
|
| - return mime.find("audio/") == std::string::npos;
|
| -}
|
| -
|
| -bool WebMediaPlayerAndroid::hasAudio() const {
|
| - // TODO(hclam): Query status of audio and return the actual value.
|
| - return true;
|
| -}
|
| -
|
| -bool WebMediaPlayerAndroid::paused() const {
|
| - return !is_playing_;
|
| -}
|
| -
|
| -bool WebMediaPlayerAndroid::seeking() const {
|
| - return seeking_;
|
| -}
|
| -
|
| -double WebMediaPlayerAndroid::duration() const {
|
| - // HTML5 spec requires duration to be NaN if readyState is HAVE_NOTHING
|
| - if (ready_state_ == WebMediaPlayer::ReadyStateHaveNothing)
|
| - return std::numeric_limits<double>::quiet_NaN();
|
| -
|
| - // TODO(wolenetz): Correctly handle durations that MediaSourcePlayer
|
| - // considers unseekable, including kInfiniteDuration().
|
| - // See http://crbug.com/248396
|
| - return duration_.InSecondsF();
|
| -}
|
| -
|
| -double WebMediaPlayerAndroid::currentTime() const {
|
| - // If the player is pending for a seek, return the seek time.
|
| - if (seeking())
|
| - return pending_seek_;
|
| - return current_time_;
|
| -}
|
| -
|
| -WebSize WebMediaPlayerAndroid::naturalSize() const {
|
| - return natural_size_;
|
| -}
|
| -
|
| -WebMediaPlayer::NetworkState WebMediaPlayerAndroid::networkState() const {
|
| - return network_state_;
|
| -}
|
| -
|
| -WebMediaPlayer::ReadyState WebMediaPlayerAndroid::readyState() const {
|
| - return ready_state_;
|
| -}
|
| -
|
| -const WebTimeRanges& WebMediaPlayerAndroid::buffered() {
|
| - if (media_source_delegate_)
|
| - return media_source_delegate_->Buffered();
|
| - return buffered_;
|
| -}
|
| -
|
| -double WebMediaPlayerAndroid::maxTimeSeekable() const {
|
| - // If we haven't even gotten to ReadyStateHaveMetadata yet then just
|
| - // return 0 so that the seekable range is empty.
|
| - if (ready_state_ < WebMediaPlayer::ReadyStateHaveMetadata)
|
| - return 0.0;
|
| -
|
| - // TODO(hclam): If this stream is not seekable this should return 0.
|
| - return duration();
|
| -}
|
| -
|
| -bool WebMediaPlayerAndroid::didLoadingProgress() const {
|
| - bool ret = did_loading_progress_;
|
| - did_loading_progress_ = false;
|
| - return ret;
|
| -}
|
| -
|
| -void WebMediaPlayerAndroid::paint(WebKit::WebCanvas* canvas,
|
| - const WebKit::WebRect& rect,
|
| - unsigned char alpha) {
|
| - NOTIMPLEMENTED();
|
| -}
|
| -
|
| -bool WebMediaPlayerAndroid::copyVideoTextureToPlatformTexture(
|
| - WebKit::WebGraphicsContext3D* web_graphics_context,
|
| - unsigned int texture,
|
| - unsigned int level,
|
| - unsigned int internal_format,
|
| - unsigned int type,
|
| - bool premultiply_alpha,
|
| - bool flip_y) {
|
| - if (!texture_id_)
|
| - return false;
|
| -
|
| - // The video is stored in an unmultiplied format, so premultiply if
|
| - // necessary.
|
| - web_graphics_context->pixelStorei(GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM,
|
| - premultiply_alpha);
|
| -
|
| - // Application itself needs to take care of setting the right flip_y
|
| - // value down to get the expected result.
|
| - // flip_y==true means to reverse the video orientation while
|
| - // flip_y==false means to keep the intrinsic orientation.
|
| - web_graphics_context->pixelStorei(GL_UNPACK_FLIP_Y_CHROMIUM, flip_y);
|
| - web_graphics_context->copyTextureCHROMIUM(GL_TEXTURE_2D, texture_id_,
|
| - texture, level, internal_format,
|
| - type);
|
| - web_graphics_context->pixelStorei(GL_UNPACK_FLIP_Y_CHROMIUM, false);
|
| - web_graphics_context->pixelStorei(GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM,
|
| - false);
|
| - return true;
|
| -}
|
| -
|
| -bool WebMediaPlayerAndroid::hasSingleSecurityOrigin() const {
|
| - if (info_loader_)
|
| - return info_loader_->HasSingleOrigin();
|
| - // The info loader may have failed.
|
| - if (source_type_ == MediaPlayerAndroid::SOURCE_TYPE_URL)
|
| - return false;
|
| - return true;
|
| -}
|
| -
|
| -bool WebMediaPlayerAndroid::didPassCORSAccessCheck() const {
|
| - if (info_loader_)
|
| - return info_loader_->DidPassCORSAccessCheck();
|
| - return false;
|
| -}
|
| -
|
| -double WebMediaPlayerAndroid::mediaTimeForTimeValue(double timeValue) const {
|
| - return ConvertSecondsToTimestamp(timeValue).InSecondsF();
|
| -}
|
| -
|
| -unsigned WebMediaPlayerAndroid::decodedFrameCount() const {
|
| - if (media_source_delegate_)
|
| - return media_source_delegate_->DecodedFrameCount();
|
| - NOTIMPLEMENTED();
|
| - return 0;
|
| -}
|
| -
|
| -unsigned WebMediaPlayerAndroid::droppedFrameCount() const {
|
| - if (media_source_delegate_)
|
| - return media_source_delegate_->DroppedFrameCount();
|
| - NOTIMPLEMENTED();
|
| - return 0;
|
| -}
|
| -
|
| -unsigned WebMediaPlayerAndroid::audioDecodedByteCount() const {
|
| - if (media_source_delegate_)
|
| - return media_source_delegate_->AudioDecodedByteCount();
|
| - NOTIMPLEMENTED();
|
| - return 0;
|
| -}
|
| -
|
| -unsigned WebMediaPlayerAndroid::videoDecodedByteCount() const {
|
| - if (media_source_delegate_)
|
| - return media_source_delegate_->VideoDecodedByteCount();
|
| - NOTIMPLEMENTED();
|
| - return 0;
|
| -}
|
| -
|
| -void WebMediaPlayerAndroid::OnMediaMetadataChanged(
|
| - base::TimeDelta duration, int width, int height, bool success) {
|
| - bool need_to_signal_duration_changed = false;
|
| -
|
| - if (url_.SchemeIs("file"))
|
| - UpdateNetworkState(WebMediaPlayer::NetworkStateLoaded);
|
| -
|
| - // Update duration, if necessary, prior to ready state updates that may
|
| - // cause duration() query.
|
| - // TODO(wolenetz): Correctly handle durations that MediaSourcePlayer
|
| - // considers unseekable, including kInfiniteDuration().
|
| - // See http://crbug.com/248396
|
| - if (!ignore_metadata_duration_change_ && duration_ != duration) {
|
| - duration_ = duration;
|
| -
|
| - // Client readyState transition from HAVE_NOTHING to HAVE_METADATA
|
| - // already triggers a durationchanged event. If this is a different
|
| - // transition, remember to signal durationchanged.
|
| - // Do not ever signal durationchanged on metadata change in MSE case
|
| - // because OnDurationChange() handles this.
|
| - if (ready_state_ > WebMediaPlayer::ReadyStateHaveNothing &&
|
| - source_type_ != MediaPlayerAndroid::SOURCE_TYPE_MSE) {
|
| - need_to_signal_duration_changed = true;
|
| - }
|
| - }
|
| -
|
| - has_media_metadata_ = true;
|
| - if (has_media_info_ &&
|
| - ready_state_ != WebMediaPlayer::ReadyStateHaveEnoughData) {
|
| - UpdateReadyState(WebMediaPlayer::ReadyStateHaveMetadata);
|
| - UpdateReadyState(WebMediaPlayer::ReadyStateHaveEnoughData);
|
| - }
|
| -
|
| - // TODO(wolenetz): Should we just abort early and set network state to an
|
| - // error if success == false? See http://crbug.com/248399
|
| - if (success)
|
| - OnVideoSizeChanged(width, height);
|
| -
|
| - if (hasVideo() && !video_weblayer_ && client_->needsWebLayerForVideo()) {
|
| - video_weblayer_.reset(
|
| - new webkit::WebLayerImpl(cc::VideoLayer::Create(this)));
|
| - client_->setWebLayer(video_weblayer_.get());
|
| - }
|
| -
|
| - if (need_to_signal_duration_changed)
|
| - client_->durationChanged();
|
| -}
|
| -
|
| -void WebMediaPlayerAndroid::OnPlaybackComplete() {
|
| - // When playback is about to finish, android media player often stops
|
| - // at a time which is smaller than the duration. This makes webkit never
|
| - // know that the playback has finished. To solve this, we set the
|
| - // current time to media duration when OnPlaybackComplete() get called.
|
| - OnTimeUpdate(duration_);
|
| - client_->timeChanged();
|
| -}
|
| -
|
| -void WebMediaPlayerAndroid::OnBufferingUpdate(int percentage) {
|
| - buffered_[0].end = duration() * percentage / 100;
|
| - did_loading_progress_ = true;
|
| -}
|
| -
|
| -void WebMediaPlayerAndroid::OnSeekComplete(base::TimeDelta current_time) {
|
| - seeking_ = false;
|
| -
|
| - OnTimeUpdate(current_time);
|
| -
|
| - UpdateReadyState(WebMediaPlayer::ReadyStateHaveEnoughData);
|
| -
|
| - client_->timeChanged();
|
| -}
|
| -
|
| -void WebMediaPlayerAndroid::OnMediaError(int error_type) {
|
| - switch (error_type) {
|
| - case MediaPlayerAndroid::MEDIA_ERROR_FORMAT:
|
| - UpdateNetworkState(WebMediaPlayer::NetworkStateFormatError);
|
| - break;
|
| - case MediaPlayerAndroid::MEDIA_ERROR_DECODE:
|
| - UpdateNetworkState(WebMediaPlayer::NetworkStateDecodeError);
|
| - break;
|
| - case MediaPlayerAndroid::MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK:
|
| - UpdateNetworkState(WebMediaPlayer::NetworkStateFormatError);
|
| - break;
|
| - case MediaPlayerAndroid::MEDIA_ERROR_INVALID_CODE:
|
| - break;
|
| - }
|
| - client_->repaint();
|
| -}
|
| -
|
| -void WebMediaPlayerAndroid::OnVideoSizeChanged(int width, int height) {
|
| - has_size_info_ = true;
|
| - if (natural_size_.width == width && natural_size_.height == height)
|
| - return;
|
| -
|
| -#if defined(GOOGLE_TV)
|
| - static bool has_switch = CommandLine::ForCurrentProcess()->HasSwitch(
|
| - switches::kUseExternalVideoSurfaceThresholdInPixels);
|
| - static int threshold = 0;
|
| - static bool parsed_arg =
|
| - has_switch &&
|
| - base::StringToInt(
|
| - CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
|
| - switches::kUseExternalVideoSurfaceThresholdInPixels),
|
| - &threshold);
|
| -
|
| - if ((parsed_arg && threshold <= width * height) ||
|
| - // Use H/W surface for MSE as the content is protected.
|
| - media_source_delegate_) {
|
| - if (stream_texture_factory_) {
|
| - stream_texture_factory_->DestroyStreamTexture(texture_id_);
|
| - stream_id_ = 0;
|
| - texture_id_ = 0;
|
| - }
|
| - needs_external_surface_ = true;
|
| - SetNeedsEstablishPeer(false);
|
| - if (!paused())
|
| - proxy_->RequestExternalSurface(player_id_, last_computed_rect_);
|
| - }
|
| -#endif
|
| -
|
| - natural_size_.width = width;
|
| - natural_size_.height = height;
|
| - ReallocateVideoFrame();
|
| -}
|
| -
|
| -void WebMediaPlayerAndroid::OnTimeUpdate(base::TimeDelta current_time) {
|
| - current_time_ = current_time.InSecondsF();
|
| -}
|
| -
|
| -void WebMediaPlayerAndroid::OnDidEnterFullscreen() {
|
| - if (!manager_->IsInFullscreen(frame_)) {
|
| - frame_->view()->willEnterFullScreen();
|
| - frame_->view()->didEnterFullScreen();
|
| - manager_->DidEnterFullscreen(frame_);
|
| - }
|
| -}
|
| -
|
| -void WebMediaPlayerAndroid::OnDidExitFullscreen() {
|
| - // |needs_external_surface_| is always false on non-TV devices.
|
| - if (!needs_external_surface_)
|
| - SetNeedsEstablishPeer(true);
|
| - // We had the fullscreen surface connected to Android MediaPlayer,
|
| - // so reconnect our surface texture for embedded playback.
|
| - if (!paused())
|
| - EstablishSurfaceTexturePeer();
|
| -
|
| - frame_->view()->willExitFullScreen();
|
| - frame_->view()->didExitFullScreen();
|
| - manager_->DidExitFullscreen();
|
| - client_->repaint();
|
| -}
|
| -
|
| -void WebMediaPlayerAndroid::OnMediaPlayerPlay() {
|
| - UpdatePlayingState(true);
|
| - client_->playbackStateChanged();
|
| -}
|
| -
|
| -void WebMediaPlayerAndroid::OnMediaPlayerPause() {
|
| - UpdatePlayingState(false);
|
| - client_->playbackStateChanged();
|
| -}
|
| -
|
| -void WebMediaPlayerAndroid::OnMediaSeekRequest(base::TimeDelta time_to_seek) {
|
| - if (!media_source_delegate_)
|
| - return;
|
| -
|
| - if (!seeking_)
|
| - media_source_delegate_->CancelPendingSeek();
|
| - media_source_delegate_->Seek(time_to_seek);
|
| - OnTimeUpdate(time_to_seek);
|
| -}
|
| -
|
| -void WebMediaPlayerAndroid::OnMediaConfigRequest() {
|
| - if (!media_source_delegate_)
|
| - return;
|
| -
|
| - media_source_delegate_->OnMediaConfigRequest();
|
| -}
|
| -
|
| -void WebMediaPlayerAndroid::OnDurationChange(const base::TimeDelta& duration) {
|
| - // Only MSE |source_type_| registers this callback.
|
| - DCHECK(source_type_ == MediaPlayerAndroid::SOURCE_TYPE_MSE);
|
| -
|
| - // Cache the new duration value and trust it over any subsequent duration
|
| - // values received in OnMediaMetadataChanged().
|
| - // TODO(wolenetz): Correctly handle durations that MediaSourcePlayer
|
| - // considers unseekable, including kInfiniteDuration().
|
| - // See http://crbug.com/248396
|
| - duration_ = duration;
|
| - ignore_metadata_duration_change_ = true;
|
| -
|
| - // Send message to Android MediaSourcePlayer to update duration.
|
| - if (proxy_)
|
| - proxy_->DurationChanged(player_id_, duration_);
|
| -
|
| - // Notify MediaPlayerClient that duration has changed, if > HAVE_NOTHING.
|
| - if (ready_state_ > WebMediaPlayer::ReadyStateHaveNothing)
|
| - client_->durationChanged();
|
| -}
|
| -
|
| -void WebMediaPlayerAndroid::UpdateNetworkState(
|
| - WebMediaPlayer::NetworkState state) {
|
| - if (ready_state_ == WebMediaPlayer::ReadyStateHaveNothing &&
|
| - (state == WebMediaPlayer::NetworkStateNetworkError ||
|
| - state == WebMediaPlayer::NetworkStateDecodeError)) {
|
| - // Any error that occurs before reaching ReadyStateHaveMetadata should
|
| - // be considered a format error.
|
| - network_state_ = WebMediaPlayer::NetworkStateFormatError;
|
| - } else {
|
| - network_state_ = state;
|
| - }
|
| - client_->networkStateChanged();
|
| -}
|
| -
|
| -void WebMediaPlayerAndroid::UpdateReadyState(
|
| - WebMediaPlayer::ReadyState state) {
|
| - ready_state_ = state;
|
| - client_->readyStateChanged();
|
| -}
|
| -
|
| -void WebMediaPlayerAndroid::OnPlayerReleased() {
|
| - // |needs_external_surface_| is always false on non-TV devices.
|
| - if (!needs_external_surface_)
|
| - needs_establish_peer_ = true;
|
| -}
|
| -
|
| -void WebMediaPlayerAndroid::ReleaseMediaResources() {
|
| - switch (network_state_) {
|
| - // Pause the media player and inform WebKit if the player is in a good
|
| - // shape.
|
| - case WebMediaPlayer::NetworkStateIdle:
|
| - case WebMediaPlayer::NetworkStateLoading:
|
| - case WebMediaPlayer::NetworkStateLoaded:
|
| - pause();
|
| - client_->playbackStateChanged();
|
| - break;
|
| - // If a WebMediaPlayer instance has entered into one of these states,
|
| - // the internal network state in HTMLMediaElement could be set to empty.
|
| - // And calling playbackStateChanged() could get this object deleted.
|
| - case WebMediaPlayer::NetworkStateEmpty:
|
| - case WebMediaPlayer::NetworkStateFormatError:
|
| - case WebMediaPlayer::NetworkStateNetworkError:
|
| - case WebMediaPlayer::NetworkStateDecodeError:
|
| - break;
|
| - }
|
| - proxy_->ReleaseResources(player_id_);
|
| - OnPlayerReleased();
|
| -}
|
| -
|
| -void WebMediaPlayerAndroid::WillDestroyCurrentMessageLoop() {
|
| - if (manager_)
|
| - manager_->UnregisterMediaPlayer(player_id_);
|
| - Detach();
|
| -}
|
| -
|
| -void WebMediaPlayerAndroid::Detach() {
|
| - if (stream_id_) {
|
| - stream_texture_factory_->DestroyStreamTexture(texture_id_);
|
| - stream_id_ = 0;
|
| - }
|
| -
|
| - media_source_delegate_.reset();
|
| - current_frame_ = NULL;
|
| - manager_ = NULL;
|
| - proxy_ = NULL;
|
| -}
|
| -
|
| -void WebMediaPlayerAndroid::ReallocateVideoFrame() {
|
| - if (needs_external_surface_) {
|
| - // VideoFrame::CreateHoleFrame is only defined under GOOGLE_TV.
|
| -#if defined(GOOGLE_TV)
|
| - if (!natural_size_.isEmpty()) {
|
| - current_frame_ = VideoFrame::CreateHoleFrame(natural_size_);
|
| - // Force the client to grab the hole frame.
|
| - client_->repaint();
|
| - }
|
| -#else
|
| - NOTIMPLEMENTED() << "Hole punching not supported outside of Google TV";
|
| -#endif
|
| - } else if (texture_id_) {
|
| - current_frame_ = VideoFrame::WrapNativeTexture(
|
| - texture_id_, kGLTextureExternalOES, natural_size_,
|
| - gfx::Rect(natural_size_), natural_size_, base::TimeDelta(),
|
| - VideoFrame::ReadPixelsCB(),
|
| - base::Closure());
|
| - }
|
| -}
|
| -
|
| -void WebMediaPlayerAndroid::SetVideoFrameProviderClient(
|
| - cc::VideoFrameProvider::Client* client) {
|
| - // This is called from both the main renderer thread and the compositor
|
| - // thread (when the main thread is blocked).
|
| - if (video_frame_provider_client_)
|
| - video_frame_provider_client_->StopUsingProvider();
|
| - video_frame_provider_client_ = client;
|
| -
|
| - // Set the callback target when a frame is produced.
|
| - if (stream_texture_proxy_)
|
| - stream_texture_proxy_->SetClient(client);
|
| -}
|
| -
|
| -scoped_refptr<media::VideoFrame> WebMediaPlayerAndroid::GetCurrentFrame() {
|
| - if (!stream_texture_proxy_initialized_ && stream_texture_proxy_ &&
|
| - stream_id_ && !needs_external_surface_) {
|
| - gfx::Size natural_size = current_frame_->natural_size();
|
| - stream_texture_proxy_->BindToCurrentThread(
|
| - stream_id_, natural_size.width(), natural_size.height());
|
| - stream_texture_proxy_initialized_ = true;
|
| - }
|
| - return current_frame_;
|
| -}
|
| -
|
| -void WebMediaPlayerAndroid::PutCurrentFrame(
|
| - const scoped_refptr<media::VideoFrame>& frame) {
|
| -}
|
| -
|
| -void WebMediaPlayerAndroid::EstablishSurfaceTexturePeer() {
|
| - if (media_source_delegate_ && stream_texture_factory_) {
|
| - // MediaCodec will release the old surface when it goes away, we need to
|
| - // recreate a new one each time this is called.
|
| - stream_texture_factory_->DestroyStreamTexture(texture_id_);
|
| - stream_id_ = 0;
|
| - texture_id_ = 0;
|
| - stream_id_ = stream_texture_factory_->CreateStreamTexture(&texture_id_);
|
| - ReallocateVideoFrame();
|
| - stream_texture_proxy_initialized_ = false;
|
| - }
|
| - if (stream_texture_factory_.get() && stream_id_)
|
| - stream_texture_factory_->EstablishPeer(stream_id_, player_id_);
|
| - needs_establish_peer_ = false;
|
| -}
|
| -
|
| -void WebMediaPlayerAndroid::SetNeedsEstablishPeer(bool needs_establish_peer) {
|
| - needs_establish_peer_ = needs_establish_peer;
|
| -}
|
| -
|
| -void WebMediaPlayerAndroid::UpdatePlayingState(bool is_playing) {
|
| - is_playing_ = is_playing;
|
| - if (source_type_ != MediaPlayerAndroid::SOURCE_TYPE_MSE || !delegate_)
|
| - return;
|
| - if (is_playing)
|
| - delegate_->DidPlay(this);
|
| - else
|
| - delegate_->DidPause(this);
|
| -}
|
| -
|
| -#if defined(GOOGLE_TV)
|
| -bool WebMediaPlayerAndroid::RetrieveGeometryChange(gfx::RectF* rect) {
|
| - if (!video_weblayer_)
|
| - return false;
|
| -
|
| - // Compute the geometry of video frame layer.
|
| - cc::Layer* layer = video_weblayer_->layer();
|
| - rect->set_size(layer->bounds());
|
| - while (layer) {
|
| - rect->Offset(layer->position().OffsetFromOrigin());
|
| - layer = layer->parent();
|
| - }
|
| -
|
| - // Return false when the geometry hasn't been changed from the last time.
|
| - if (last_computed_rect_ == *rect)
|
| - return false;
|
| -
|
| - // Store the changed geometry information when it is actually changed.
|
| - last_computed_rect_ = *rect;
|
| - return true;
|
| -}
|
| -#endif
|
| -
|
| -// The following EME related code is copied from WebMediaPlayerImpl.
|
| -// TODO(xhwang): Remove duplicate code between WebMediaPlayerAndroid and
|
| -// WebMediaPlayerImpl.
|
| -// TODO(kjyoun): Update Google TV EME implementation to use IPC.
|
| -
|
| -// Helper functions to report media EME related stats to UMA. They follow the
|
| -// convention of more commonly used macros UMA_HISTOGRAM_ENUMERATION and
|
| -// UMA_HISTOGRAM_COUNTS. The reason that we cannot use those macros directly is
|
| -// that UMA_* macros require the names to be constant throughout the process'
|
| -// lifetime.
|
| -static void EmeUMAHistogramEnumeration(const std::string& key_system,
|
| - const std::string& method,
|
| - int sample,
|
| - int boundary_value) {
|
| - base::LinearHistogram::FactoryGet(
|
| - kMediaEme + KeySystemNameForUMA(key_system) + "." + method,
|
| - 1, boundary_value, boundary_value + 1,
|
| - base::Histogram::kUmaTargetedHistogramFlag)->Add(sample);
|
| -}
|
| -
|
| -static void EmeUMAHistogramCounts(const std::string& key_system,
|
| - const std::string& method,
|
| - int sample) {
|
| - // Use the same parameters as UMA_HISTOGRAM_COUNTS.
|
| - base::Histogram::FactoryGet(
|
| - kMediaEme + KeySystemNameForUMA(key_system) + "." + method,
|
| - 1, 1000000, 50, base::Histogram::kUmaTargetedHistogramFlag)->Add(sample);
|
| -}
|
| -
|
| -// Helper enum for reporting generateKeyRequest/addKey histograms.
|
| -enum MediaKeyException {
|
| - kUnknownResultId,
|
| - kSuccess,
|
| - kKeySystemNotSupported,
|
| - kInvalidPlayerState,
|
| - kMaxMediaKeyException
|
| -};
|
| -
|
| -static MediaKeyException MediaKeyExceptionForUMA(
|
| - WebMediaPlayer::MediaKeyException e) {
|
| - switch (e) {
|
| - case WebMediaPlayer::MediaKeyExceptionKeySystemNotSupported:
|
| - return kKeySystemNotSupported;
|
| - case WebMediaPlayer::MediaKeyExceptionInvalidPlayerState:
|
| - return kInvalidPlayerState;
|
| - case WebMediaPlayer::MediaKeyExceptionNoError:
|
| - return kSuccess;
|
| - default:
|
| - return kUnknownResultId;
|
| - }
|
| -}
|
| -
|
| -// Helper for converting |key_system| name and exception |e| to a pair of enum
|
| -// values from above, for reporting to UMA.
|
| -static void ReportMediaKeyExceptionToUMA(
|
| - const std::string& method,
|
| - const WebString& key_system,
|
| - WebMediaPlayer::MediaKeyException e) {
|
| - MediaKeyException result_id = MediaKeyExceptionForUMA(e);
|
| - DCHECK_NE(result_id, kUnknownResultId) << e;
|
| - EmeUMAHistogramEnumeration(
|
| - key_system.utf8(), method, result_id, kMaxMediaKeyException);
|
| -}
|
| -
|
| -WebMediaPlayer::MediaKeyException WebMediaPlayerAndroid::generateKeyRequest(
|
| - const WebString& key_system,
|
| - const unsigned char* init_data,
|
| - unsigned init_data_length) {
|
| - WebMediaPlayer::MediaKeyException e =
|
| - GenerateKeyRequestInternal(key_system, init_data, init_data_length);
|
| - ReportMediaKeyExceptionToUMA("generateKeyRequest", key_system, e);
|
| - return e;
|
| -}
|
| -
|
| -WebMediaPlayer::MediaKeyException
|
| -WebMediaPlayerAndroid::GenerateKeyRequestInternal(
|
| - const WebString& key_system,
|
| - const unsigned char* init_data,
|
| - unsigned init_data_length) {
|
| - DVLOG(1) << "generateKeyRequest: " << key_system.utf8().data() << ": "
|
| - << std::string(reinterpret_cast<const char*>(init_data),
|
| - static_cast<size_t>(init_data_length));
|
| -
|
| - if (!IsSupportedKeySystem(key_system))
|
| - return WebMediaPlayer::MediaKeyExceptionKeySystemNotSupported;
|
| -
|
| - // We do not support run-time switching between key systems for now.
|
| - if (current_key_system_.isEmpty()) {
|
| - if (!decryptor_->InitializeCDM(key_system.utf8()))
|
| - return WebMediaPlayer::MediaKeyExceptionKeySystemNotSupported;
|
| - current_key_system_ = key_system;
|
| - } else if (key_system != current_key_system_) {
|
| - return WebMediaPlayer::MediaKeyExceptionInvalidPlayerState;
|
| - }
|
| -
|
| - // TODO(xhwang): We assume all streams are from the same container (thus have
|
| - // the same "type") for now. In the future, the "type" should be passed down
|
| - // from the application.
|
| - if (!decryptor_->GenerateKeyRequest(init_data_type_,
|
| - init_data, init_data_length)) {
|
| - current_key_system_.reset();
|
| - return WebMediaPlayer::MediaKeyExceptionKeySystemNotSupported;
|
| - }
|
| -
|
| - return WebMediaPlayer::MediaKeyExceptionNoError;
|
| -}
|
| -
|
| -WebMediaPlayer::MediaKeyException WebMediaPlayerAndroid::addKey(
|
| - const WebString& key_system,
|
| - const unsigned char* key,
|
| - unsigned key_length,
|
| - const unsigned char* init_data,
|
| - unsigned init_data_length,
|
| - const WebString& session_id) {
|
| - WebMediaPlayer::MediaKeyException e = AddKeyInternal(
|
| - key_system, key, key_length, init_data, init_data_length, session_id);
|
| - ReportMediaKeyExceptionToUMA("addKey", key_system, e);
|
| - return e;
|
| -}
|
| -
|
| -WebMediaPlayer::MediaKeyException WebMediaPlayerAndroid::AddKeyInternal(
|
| - const WebString& key_system,
|
| - const unsigned char* key,
|
| - unsigned key_length,
|
| - const unsigned char* init_data,
|
| - unsigned init_data_length,
|
| - const WebString& session_id) {
|
| - DCHECK(key);
|
| - DCHECK_GT(key_length, 0u);
|
| - DVLOG(1) << "addKey: " << key_system.utf8().data() << ": "
|
| - << std::string(reinterpret_cast<const char*>(key),
|
| - static_cast<size_t>(key_length)) << ", "
|
| - << std::string(reinterpret_cast<const char*>(init_data),
|
| - static_cast<size_t>(init_data_length))
|
| - << " [" << session_id.utf8().data() << "]";
|
| -
|
| - if (!IsSupportedKeySystem(key_system))
|
| - return WebMediaPlayer::MediaKeyExceptionKeySystemNotSupported;
|
| -
|
| - if (current_key_system_.isEmpty() || key_system != current_key_system_)
|
| - return WebMediaPlayer::MediaKeyExceptionInvalidPlayerState;
|
| -
|
| - decryptor_->AddKey(key, key_length, init_data, init_data_length,
|
| - session_id.utf8());
|
| - return WebMediaPlayer::MediaKeyExceptionNoError;
|
| -}
|
| -
|
| -WebMediaPlayer::MediaKeyException WebMediaPlayerAndroid::cancelKeyRequest(
|
| - const WebString& key_system,
|
| - const WebString& session_id) {
|
| - WebMediaPlayer::MediaKeyException e =
|
| - CancelKeyRequestInternal(key_system, session_id);
|
| - ReportMediaKeyExceptionToUMA("cancelKeyRequest", key_system, e);
|
| - return e;
|
| -}
|
| -
|
| -WebMediaPlayer::MediaKeyException
|
| -WebMediaPlayerAndroid::CancelKeyRequestInternal(
|
| - const WebString& key_system,
|
| - const WebString& session_id) {
|
| - if (!IsSupportedKeySystem(key_system))
|
| - return WebMediaPlayer::MediaKeyExceptionKeySystemNotSupported;
|
| -
|
| - if (current_key_system_.isEmpty() || key_system != current_key_system_)
|
| - return WebMediaPlayer::MediaKeyExceptionInvalidPlayerState;
|
| -
|
| - decryptor_->CancelKeyRequest(session_id.utf8());
|
| - return WebMediaPlayer::MediaKeyExceptionNoError;
|
| -}
|
| -
|
| -void WebMediaPlayerAndroid::OnKeyAdded(const std::string& session_id) {
|
| - EmeUMAHistogramCounts(current_key_system_.utf8(), "KeyAdded", 1);
|
| -
|
| - if (media_source_delegate_)
|
| - media_source_delegate_->NotifyKeyAdded(current_key_system_.utf8());
|
| -
|
| - client_->keyAdded(current_key_system_, WebString::fromUTF8(session_id));
|
| -}
|
| -
|
| -void WebMediaPlayerAndroid::OnKeyError(const std::string& session_id,
|
| - media::MediaKeys::KeyError error_code,
|
| - int system_code) {
|
| - EmeUMAHistogramEnumeration(current_key_system_.utf8(), "KeyError",
|
| - error_code, media::MediaKeys::kMaxKeyError);
|
| -
|
| - client_->keyError(
|
| - current_key_system_,
|
| - WebString::fromUTF8(session_id),
|
| - static_cast<WebKit::WebMediaPlayerClient::MediaKeyErrorCode>(error_code),
|
| - system_code);
|
| -}
|
| -
|
| -void WebMediaPlayerAndroid::OnKeyMessage(const std::string& session_id,
|
| - const std::string& message,
|
| - const std::string& destination_url) {
|
| - const GURL destination_url_gurl(destination_url);
|
| - DLOG_IF(WARNING, !destination_url.empty() && !destination_url_gurl.is_valid())
|
| - << "Invalid URL in destination_url: " << destination_url;
|
| -
|
| - client_->keyMessage(current_key_system_,
|
| - WebString::fromUTF8(session_id),
|
| - reinterpret_cast<const uint8*>(message.data()),
|
| - message.size(),
|
| - destination_url_gurl);
|
| -}
|
| -
|
| -void WebMediaPlayerAndroid::OnNeedKey(const std::string& session_id,
|
| - const std::string& type,
|
| - scoped_ptr<uint8[]> init_data,
|
| - int init_data_size) {
|
| - // Do not fire NeedKey event if encrypted media is not enabled.
|
| - if (!WebKit::WebRuntimeFeatures::isEncryptedMediaEnabled() &&
|
| - !WebKit::WebRuntimeFeatures::isLegacyEncryptedMediaEnabled()) {
|
| - return;
|
| - }
|
| -
|
| - UMA_HISTOGRAM_COUNTS(kMediaEme + std::string("NeedKey"), 1);
|
| -
|
| - DCHECK(init_data_type_.empty() || type.empty() || type == init_data_type_);
|
| - if (init_data_type_.empty())
|
| - init_data_type_ = type;
|
| -
|
| - client_->keyNeeded(WebString(),
|
| - WebString::fromUTF8(session_id),
|
| - init_data.get(),
|
| - init_data_size);
|
| -}
|
| -
|
| -#if defined(GOOGLE_TV)
|
| -bool WebMediaPlayerAndroid::InjectMediaStream(
|
| - MediaStreamClient* media_stream_client,
|
| - media::Demuxer* demuxer,
|
| - const base::Closure& destroy_demuxer_cb) {
|
| - DCHECK(!demuxer);
|
| - media_stream_client_ = media_stream_client;
|
| - demuxer_ = demuxer;
|
| - destroy_demuxer_cb_ = destroy_demuxer_cb;
|
| - return true;
|
| -}
|
| -#endif
|
| -
|
| -void WebMediaPlayerAndroid::OnReadFromDemuxer(
|
| - media::DemuxerStream::Type type, bool seek_done) {
|
| - if (media_source_delegate_)
|
| - media_source_delegate_->OnReadFromDemuxer(type, seek_done);
|
| - else
|
| - NOTIMPLEMENTED();
|
| -}
|
| -
|
| -void WebMediaPlayerAndroid::enterFullscreen() {
|
| - if (manager_->CanEnterFullscreen(frame_)) {
|
| - proxy_->EnterFullscreen(player_id_);
|
| - SetNeedsEstablishPeer(false);
|
| - }
|
| -}
|
| -
|
| -void WebMediaPlayerAndroid::exitFullscreen() {
|
| - proxy_->ExitFullscreen(player_id_);
|
| -}
|
| -
|
| -bool WebMediaPlayerAndroid::canEnterFullscreen() const {
|
| - return manager_->CanEnterFullscreen(frame_);
|
| -}
|
| -
|
| -} // namespace webkit_media
|
|
|