Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(673)

Unified Diff: webkit/media/android/webmediaplayer_android.cc

Issue 10073016: Upstream WebMediaPlayerAndroid as WebKit::WebMediaPlayer implementation on android. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: webkit/media/android/webmediaplayer_android.cc
diff --git a/webkit/media/android/webmediaplayer_android.cc b/webkit/media/android/webmediaplayer_android.cc
new file mode 100644
index 0000000000000000000000000000000000000000..30a1b2c8ea2ea71094a479d05332531a8b6b8809
--- /dev/null
+++ b/webkit/media/android/webmediaplayer_android.cc
@@ -0,0 +1,520 @@
+// 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.
+
+#include "webkit/media/android/webmediaplayer_android.h"
+
+#include <string>
+
+#include "base/bind.h"
+#include "base/command_line.h"
+#include "base/file_path.h"
+#include "base/logging.h"
+#include "base/utf_string_conversions.h"
+#include "media/base/android/media_player_bridge.h"
+#include "net/base/mime_util.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebMediaPlayerClient.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebCookieJar.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebRect.h"
+#include "webkit/media/android/webmediaplayer_proxy_android.h"
+#include "webkit/media/webvideoframe_impl.h"
+
+using WebKit::WebCanvas;
+using WebKit::WebFrame;
+using WebKit::WebMediaPlayerClient;
+using WebKit::WebMediaPlayer;
+using WebKit::WebRect;
+using WebKit::WebSize;
+using WebKit::WebTimeRanges;
+using WebKit::WebURL;
+using WebKit::WebVideoFrame;
+using media::MediaPlayerBridge;
+using media::VideoFrame;
+using webkit_media::WebVideoFrameImpl;
+
+namespace {
+
+// Platform independent method for converting and rounding floating point
+// seconds to an int64 timestamp.
+//
+// Refer to https://bugs.webkit.org/show_bug.cgi?id=52697 for details.
+base::TimeDelta ConvertSecondsToTimestamp(float seconds) {
scherkus (not reviewing) 2012/04/17 03:57:31 this code is duplicated
qinmin 2012/04/18 20:06:30 move the function to webmediaplayer_util.h, and al
+ float microseconds = seconds * base::Time::kMicrosecondsPerSecond;
+ float integer = ceilf(microseconds);
+ float difference = integer - microseconds;
+
+ // Round down if difference is large enough.
+ if ((microseconds > 0 && difference > 0.5f) ||
+ (microseconds <= 0 && difference >= 0.5f)) {
+ integer -= 1.0f;
+ }
+
+ // Now we can safely cast to int64 microseconds.
+ return base::TimeDelta::FromMicroseconds(static_cast<int64>(integer));
+}
+
+} // namespace
+
+namespace webkit_media {
+
+bool WebMediaPlayerAndroid::incognito_mode_ = false;
+
+WebMediaPlayerAndroid::WebMediaPlayerAndroid(
+ WebFrame* frame,
+ WebMediaPlayerClient* client,
+ WebKit::WebCookieJar* cookie_jar)
+ : frame_(frame),
scherkus (not reviewing) 2012/04/17 03:57:31 WMPA doesn't use this
qinmin 2012/04/18 20:06:30 This will be used by the fullscreen view code to g
+ client_(client),
+ render_message_loop_(base::MessageLoopProxy::current()),
scherkus (not reviewing) 2012/04/17 03:57:31 WMPA doesn't use this
qinmin 2012/04/18 20:06:30 Done.
+ media_player_(NULL),
scherkus (not reviewing) 2012/04/17 03:57:31 for scoped_ptr/scoped_refptr we typically leave th
qinmin 2012/04/18 20:06:30 Done.
+ natural_size_(WebSize(0,0)),
scherkus (not reviewing) 2012/04/17 03:57:31 this is handles by default ctor -- no need to have
qinmin 2012/04/18 20:06:30 Done.
+ proxy_(new WebMediaPlayerProxyAndroid(render_message_loop_)),
+ prepared_(false),
+ duration_(0),
+ time_to_seek_(0),
+ seeking_(false),
+ current_time_(0),
+ buffered_bytes_(0),
+ cookie_jar_(cookie_jar),
+ pending_play_event_(false),
+ skip_loading_(false),
+ network_state_(WebMediaPlayer::Empty),
+ ready_state_(WebMediaPlayer::HaveNothing) {
+ video_frame_.reset(new WebVideoFrameImpl(VideoFrame::CreateEmptyFrame()));
+}
+
+WebMediaPlayerAndroid::~WebMediaPlayerAndroid() {
+ proxy_->SetWebMediaPlayer(NULL);
+
+ if (media_player_.get()) {
+ media_player_->Stop();
+ media_player_.reset(NULL);
scherkus (not reviewing) 2012/04/17 03:57:31 do you need this line? the dtor should call this a
qinmin 2012/04/18 20:06:30 Done.
+ }
+
+ video_frame_.reset(NULL);
scherkus (not reviewing) 2012/04/17 03:57:31 ditto
qinmin 2012/04/18 20:06:30 Done.
+}
+
+void WebMediaPlayerAndroid::InitIncognito(bool incognito_mode) {
+ incognito_mode_ = incognito_mode;
scherkus (not reviewing) 2012/04/17 03:57:31 when is this called? is it guaranteed this will ge
qinmin 2012/04/18 20:06:30 This will be called by chrome/browser/chrome_conte
scherkus (not reviewing) 2012/04/21 03:02:05 What you describe are all implementation details o
+}
+
+void WebMediaPlayerAndroid::load(const WebURL& url) {
+ url_ = url;
scherkus (not reviewing) 2012/04/17 03:57:31 most of your url_ usage involves immediately conve
qinmin 2012/04/18 20:06:30 Done.
+ GURL gurl(url_);
+
+ // Calling LoadUrl will cause android mediaplayer to start buffering and
+ // decoding the data. On mobile devices, this costs a lot of data usage
+ // and could even introduce performance issues. So we don't load the url
+ // unless it is a local file. We will start loading the media only when
+ // play/seek/fullsceen button is clicked.
scherkus (not reviewing) 2012/04/17 03:57:31 as a web page author can't I work around this by h
qinmin 2012/04/18 20:06:30 No, calling play() will not work as there are gest
scherkus (not reviewing) 2012/04/21 03:02:05 Thanks for the explanation! On 2012/04/18 20:06:3
+ if (gurl.SchemeIs("file"))
+ LoadUrl(url_);
+ else
+ skip_loading_ = true;
+
+ UpdateNetworkState(WebMediaPlayer::Loading);
+ UpdateReadyState(WebMediaPlayer::HaveNothing);
+
+ if (skip_loading_) {
scherkus (not reviewing) 2012/04/17 03:57:31 you can replace skip_loading_ with a check for med
qinmin 2012/04/18 20:06:30 rewrite the handle to file:// case On 2012/04/17 0
+ // FIXME(qinmin): we need a method to calculate the duration of the media.
scherkus (not reviewing) 2012/04/17 03:57:31 s/FIXME/TODO
qinmin 2012/04/18 20:06:30 Done.
+ // Android does not provide any function to do that.
+ // Set the initial duration value to 100 seconds so that user can touch
+ // the seek bar to perform seek. We will scale the seek position later
+ // when we got the actual duration.
+ duration_ = 100;
scherkus (not reviewing) 2012/04/17 03:57:31 you shouldn't need a duration_ parameter at all i
qinmin 2012/04/18 20:06:30 We need the duration_ for many reasons: 1. MediaPl
+
+ // Pretend everything has been loaded so that webkit can
+ // still call play() and seek().
+ UpdateReadyState(WebMediaPlayer::HaveMetadata);
+ UpdateReadyState(WebMediaPlayer::HaveEnoughData);
+ }
+}
+
+void WebMediaPlayerAndroid::cancelLoad() {
+ NOTIMPLEMENTED();
+}
+
+void WebMediaPlayerAndroid::play() {
+ if (media_player_.get()) {
+ if (!prepared_)
+ pending_play_event_ = true;
+ else
+ PlayInternal();
+ } else {
+ pending_play_event_ = true;
+ LoadUrl(url_);
+ }
+}
+
+void WebMediaPlayerAndroid::pause() {
+ if (media_player_.get()) {
+ if (!prepared_)
+ pending_play_event_ = false;
+ else
+ PauseInternal();
+ } else {
+ // We don't need to load media if pause is called().
scherkus (not reviewing) 2012/04/17 03:57:31 pause() instead of called()?
qinmin 2012/04/18 20:06:30 Done.
+ pending_play_event_ = false;
+ }
+}
+
+void WebMediaPlayerAndroid::seek(float seconds) {
+ // Record the time to seek when OnMediaPrepared() is called.
+ time_to_seek_ = seconds;
scherkus (not reviewing) 2012/04/17 03:57:31 perhaps a better variable name is "pending_seek_"
qinmin 2012/04/18 20:06:30 Done.
+ if (media_player_.get()) {
+ if (prepared_)
+ SeekInternal(seconds);
+ } else
+ LoadUrl(url_);
scherkus (not reviewing) 2012/04/17 03:57:31 curly braces please
qinmin 2012/04/18 20:06:30 Done.
+}
+
+bool WebMediaPlayerAndroid::supportsFullscreen() const {
+ return true;
+}
+
+bool WebMediaPlayerAndroid::supportsSave() const {
+ return false;
+}
+
+void WebMediaPlayerAndroid::setEndTime(float seconds) {
+ // Deprecated.
scherkus (not reviewing) 2012/04/17 03:57:31 for these and others: if they're deprecated are th
qinmin 2012/04/18 20:06:30 No, there are no bugs filed. Added a todo for this
+}
+
+void WebMediaPlayerAndroid::setRate(float rate) {
+ NOTIMPLEMENTED();
+}
+
+void WebMediaPlayerAndroid::setVolume(float volume) {
+ media_player_->SetVolume(volume, volume);
+}
+
+void WebMediaPlayerAndroid::setVisible(bool visible) {
+ // Deprecated.
+}
+
+bool WebMediaPlayerAndroid::totalBytesKnown() {
+ NOTIMPLEMENTED();
+ return false;
+}
+
+bool WebMediaPlayerAndroid::hasVideo() const {
+ // FIXME(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 (!prepared_) {
+ GURL gurl(url_);
+ if(!gurl.has_path())
scherkus (not reviewing) 2012/04/17 03:57:31 space between if and (
qinmin 2012/04/18 20:06:30 Done.
+ return false;
+ std::string mime;
+ if(!net::GetMimeTypeFromFile(FilePath(gurl.path()), &mime))
+ return true;
+ return mime.find("audio") == std::string::npos;
scherkus (not reviewing) 2012/04/17 03:57:31 should this be "audio/"?
qinmin 2012/04/18 20:06:30 Done, but should have the same effect for all curr
+ }
+
+ return natural_size_.width != 0 && natural_size_.height != 0;
scherkus (not reviewing) 2012/04/17 03:57:31 how about !natural_size_.isEmpty() instead?
qinmin 2012/04/18 20:06:30 Done.
+}
+
+bool WebMediaPlayerAndroid::hasAudio() const {
+ // TODO(hclam): Query status of audio and return the actual value.
+ return true;
+}
+
+bool WebMediaPlayerAndroid::paused() const {
+ if (!prepared_)
+ return !pending_play_event_;
+ return !media_player_->IsPlaying();
+}
+
+bool WebMediaPlayerAndroid::seeking() const {
+ return seeking_;
+}
+
+float WebMediaPlayerAndroid::duration() const {
+ return duration_;
+}
+
+float WebMediaPlayerAndroid::currentTime() const {
+ // If the player is pending for a seek, return the seek time.
+ if (!prepared_ || seeking())
+ return time_to_seek_;
+
+ // 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 PLAYBACK_COMPLETE message is
scherkus (not reviewing) 2012/04/17 03:57:31 by "PLAYBACK_COMPLETE message" do you mean OnPlayb
qinmin 2012/04/18 20:06:30 Done.
+ // received. And return the greater of the two values so that the current
+ // time is most updated.
+ return std::max(current_time_,
scherkus (not reviewing) 2012/04/17 03:57:31 current_time_ is completely misleading as it's eit
qinmin 2012/04/18 20:06:30 current_time was used to send the current time inf
+ (float) media_player_->GetCurrentTime().InSecondsF());
scherkus (not reviewing) 2012/04/17 03:57:31 static_cast<>
qinmin 2012/04/18 20:06:30 Done.
+}
+
+int WebMediaPlayerAndroid::dataRate() const {
+ // Deprecated.
+ return 0;
+}
+
+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() {
+ return time_ranges_;
+}
+
+float WebMediaPlayerAndroid::maxTimeSeekable() const {
+ // TODO(hclam): If this stream is not seekable this should return 0.
+ return duration();
+}
+
+unsigned long long WebMediaPlayerAndroid::bytesLoaded() const {
+ return buffered_bytes_;
+}
+
+unsigned long long WebMediaPlayerAndroid::totalBytes() const {
+ // Deprecated.
+ return 0;
+}
+
+void WebMediaPlayerAndroid::setSize(const WebSize& size) {
+ texture_size_ = size;
+}
+
+void WebMediaPlayerAndroid::paint(WebCanvas* canvas, const WebRect& rect) {
+ NOTIMPLEMENTED();
+}
+
+bool WebMediaPlayerAndroid::hasSingleSecurityOrigin() const {
+ return false;
+}
+
+WebMediaPlayer::MovieLoadType
+ WebMediaPlayerAndroid::movieLoadType() const {
+ // Deprecated.
+ return WebMediaPlayer::Unknown;
+}
+
+float WebMediaPlayerAndroid::mediaTimeForTimeValue(float timeValue) const {
+ return ConvertSecondsToTimestamp(timeValue).InSecondsF();
+}
+
+unsigned WebMediaPlayerAndroid::decodedFrameCount() const {
+ NOTIMPLEMENTED();
+ return 0;
+}
+
+unsigned WebMediaPlayerAndroid::droppedFrameCount() const {
+ NOTIMPLEMENTED();
+ return 0;
+}
+
+unsigned WebMediaPlayerAndroid::audioDecodedByteCount() const {
+ NOTIMPLEMENTED();
+ return 0;
+}
+
+unsigned WebMediaPlayerAndroid::videoDecodedByteCount() const {
+ NOTIMPLEMENTED();
+ return 0;
+}
+
+void WebMediaPlayerAndroid::OnMediaPrepared() {
+ WebKit::WebTimeRanges new_buffered(static_cast<size_t>(1));
+ new_buffered[0].start = 0.0f;
scherkus (not reviewing) 2012/04/17 03:57:31 WebTimeRanges's default ctor initializes to 0
qinmin 2012/04/18 20:06:30 Done.
+ new_buffered[0].end = 0.0f;
+ time_ranges_.swap(new_buffered);
scherkus (not reviewing) 2012/04/17 03:57:31 why the swap? how often is OnMediaPrepared() calle
qinmin 2012/04/18 20:06:30 This could be called many times as MediaPlayer cou
+ prepared_ = true;
+
+ // Update the media duration first so that webkit will get the correct
+ // duration when UpdateReadyState is called.
+ float dur = duration_;
+ duration_ = media_player_->GetDuration().InSecondsF();
+
+ GURL gurl(url_);
+ if (gurl.SchemeIs("file"))
+ UpdateNetworkState(WebMediaPlayer::Loaded);
+
+ if (ready_state_ != WebMediaPlayer::HaveEnoughData) {
+ UpdateReadyState(WebMediaPlayer::HaveMetadata);
+ UpdateReadyState(WebMediaPlayer::HaveEnoughData);
+ } else {
+ // If the status is already set to HaveEnoughData, set it again to make sure
+ // that Videolayerchromium will get created.
+ UpdateReadyState(WebMediaPlayer::HaveEnoughData);
+ }
+
+ if (skip_loading_) {
+ // In we have skipped loading, the duration was preset to 100 sec.
+ // We have to update webkit about the new duration.
scherkus (not reviewing) 2012/04/17 03:57:31 even in the file:// case isn't the duration also u
qinmin 2012/04/18 20:06:30 So here is what happens: WebKit will call duration
+ if (duration_ != dur) {
+ // Scale the time_to_seek_ according to the new duration.
+ time_to_seek_ = time_to_seek_ * duration_ / 100.0f;
+ client_->durationChanged();
+ }
+ }
+
+ // If media player was recovered from a saved state, consume all the pending
+ // events.
+ seek(time_to_seek_);
+
+ if (pending_play_event_)
+ PlayInternal();
+
+ pending_play_event_ = false;
+}
+
+void WebMediaPlayerAndroid::OnPlaybackComplete() {
+ // Set the current time equal to duration to let webkit know that play back
+ // is completed.
+ current_time_ = duration();
+ client_->timeChanged();
+}
+
+void WebMediaPlayerAndroid::OnBufferingUpdate(int percentage) {
+ if (time_ranges_.size() > 0) {
scherkus (not reviewing) 2012/04/17 03:57:31 would OnBufferingUpdate() ever get called before O
qinmin 2012/04/18 20:06:30 Yes, that could happen as mediaplayer could get de
scherkus (not reviewing) 2012/04/21 03:02:05 But time_ranges_ is never reset back to size 0 and
+ time_ranges_[0].end = duration() * percentage / 100;
+ // Implement a trick here to fake progress event, as WebKit checks
+ // consecutive bytesLoaded() to see if any progress made.
+ // See HTMLMediaElement::progressEventTimerFired.
+ buffered_bytes_++;
scherkus (not reviewing) 2012/04/17 03:57:31 FYI this is a pretty horrible trick! can you at l
qinmin 2012/04/18 20:06:30 TODO added, android mediaplayer does not provide u
scherkus (not reviewing) 2012/04/21 03:02:05 You should send a patch to WebKit :) In fact in r
+ }
+}
+
+void WebMediaPlayerAndroid::OnSeekComplete() {
+ seeking_ = false;
+
+ UpdateReadyState(WebMediaPlayer::HaveEnoughData);
+
+ client_->timeChanged();
+}
+
+void WebMediaPlayerAndroid::OnMediaError(int error_type) {
+ switch (error_type) {
+ case MediaPlayerBridge::MEDIA_ERROR_UNKNOWN:
+ // When playing an bogus URL or bad file, we fire an MEDIA_ERROR_UNKNOWN.
scherkus (not reviewing) 2012/04/17 03:57:31 s/an/a s/,//
qinmin 2012/04/18 20:06:30 Done.
+ // As WebKit uses FormatError to indicate an error for bogus URL or bad
+ // file, we default an MEDIA_ERROR_UNKNOWN to FormatError.
scherkus (not reviewing) 2012/04/17 03:57:31 s/an/a s/,//
qinmin 2012/04/18 20:06:30 Done.
+ UpdateNetworkState(WebMediaPlayer::FormatError);
+ break;
+ case MediaPlayerBridge::MEDIA_ERROR_SERVER_DIED:
+ // TODO(zhenghao): Media server died. In this case, the application must
+ // release the MediaPlayer object and instantiate a new one.
+ UpdateNetworkState(WebMediaPlayer::DecodeError);
+ break;
+ case MediaPlayerBridge::MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK:
+ UpdateNetworkState(WebMediaPlayer::FormatError);
+ break;
+ case MediaPlayerBridge::MEDIA_ERROR_INVALID_CODE:
+ break;
+ }
+ client_->repaint();
+}
+
+void WebMediaPlayerAndroid::OnMediaInfo(int info_type) {
+ NOTIMPLEMENTED();
+}
+
+void WebMediaPlayerAndroid::OnVideoSizeChanged(int width, int height) {
+ natural_size_.width = width;
+ natural_size_.height = height;
+}
+
+void WebMediaPlayerAndroid::UpdateNetworkState(
+ WebMediaPlayer::NetworkState state) {
+ network_state_ = state;
+ client_->networkStateChanged();
+}
+
+void WebMediaPlayerAndroid::UpdateReadyState(
+ WebMediaPlayer::ReadyState state) {
+ ready_state_ = state;
+ client_->readyStateChanged();
+}
+
+void WebMediaPlayerAndroid::SetVideoSurface(
scherkus (not reviewing) 2012/04/17 03:57:31 nit: this can fit on single line
qinmin 2012/04/18 20:06:30 Done.
+ jobject j_surface) {
+ if (media_player_.get())
+ media_player_->SetVideoSurface(j_surface);
+}
+
+void WebMediaPlayerAndroid::InitializeMediaPlayer() {
+ if (!media_player_.get()) {
scherkus (not reviewing) 2012/04/17 03:57:31 this check isn't needed -- you only call this meth
qinmin 2012/04/18 20:06:30 Changed it to a CHECK instead. On 2012/04/17 03:5
+ prepared_ = false;
+ media_player_.reset(new MediaPlayerBridge());
+ media_player_->SetStayAwakeWhilePlaying();
+ proxy_->SetWebMediaPlayer(this);
+ }
+}
+
+void WebMediaPlayerAndroid::LoadUrl(WebURL url) {
scherkus (not reviewing) 2012/04/17 03:57:31 AFAIK this only gets called once during the lifeti
qinmin 2012/04/18 20:06:30 This could get called many times since we will rel
+ if (!media_player_.get())
+ InitializeMediaPlayer();
+
+ media_player_->Reset();
scherkus (not reviewing) 2012/04/17 03:57:31 not needed since LoadUrl() should only get called
qinmin 2012/04/18 20:06:30 Done.
+
+ std::string cookies;
+ if (cookie_jar_ != NULL)
scherkus (not reviewing) 2012/04/17 03:57:31 is it valid to pass in a NULL cookie_jar to this c
qinmin 2012/04/18 20:06:30 Yes, for DRT case. On 2012/04/17 03:57:31, scherk
scherkus (not reviewing) 2012/04/21 03:02:05 There's no DRT-specific cookie jar implementation
+ cookies = UTF16ToUTF8(cookie_jar_->cookies(url, url));
+ media_player_->SetDataSource(url.spec(), cookies, incognito_mode_);
+
+ media_player_->Prepare(
+ base::Bind(&WebMediaPlayerProxyAndroid::MediaInfoCallback, proxy_),
+ base::Bind(&WebMediaPlayerProxyAndroid::MediaErrorCallback, proxy_),
+ base::Bind(&WebMediaPlayerProxyAndroid::VideoSizeChangedCallback, proxy_),
+ base::Bind(&WebMediaPlayerProxyAndroid::BufferingUpdateCallback, proxy_),
+ base::Bind(&WebMediaPlayerProxyAndroid::MediaPreparedCallback, proxy_));
+
scherkus (not reviewing) 2012/04/17 03:57:31 nit: remove blank line
qinmin 2012/04/18 20:06:30 Done.
+}
+
+void WebMediaPlayerAndroid::PlayInternal() {
+ CHECK(prepared_);
+
+ if (paused())
+ media_player_->Start(base::Bind(
+ &WebMediaPlayerProxyAndroid::PlaybackCompleteCallback, proxy_));
+}
+
+void WebMediaPlayerAndroid::PauseInternal() {
+ CHECK(prepared_);
+ media_player_->Pause();
+}
+
+void WebMediaPlayerAndroid::SeekInternal(float seconds) {
+ CHECK(prepared_);
+ if (seconds == 0.0f && currentTime() == 0.0f) {
scherkus (not reviewing) 2012/04/17 03:57:31 what's this for?
qinmin 2012/04/18 20:06:30 This is just to save some unnecessary calls to the
+ client_->timeChanged();
+ return;
+ }
+ seeking_ = true;
+ media_player_->SeekTo(ConvertSecondsToTimestamp(seconds), base::Bind(
+ &WebMediaPlayerProxyAndroid::SeekCompleteCallback, proxy_));
+}
+
+// -------------------------------------------------------------------------
+// Methods that are called on the compositor thread if useThreadedCompositor
+// flag is set.
scherkus (not reviewing) 2012/04/17 03:57:31 you've already covered this in the .h -- I'd remov
qinmin 2012/04/18 20:06:30 Done.
+WebVideoFrame* WebMediaPlayerAndroid::getCurrentFrame() {
+ return video_frame_.get();
+}
+
+void WebMediaPlayerAndroid::putCurrentFrame(
+ WebVideoFrame* web_video_frame) {
+}
+
+// -------------------------------------------------------------------------
+
+} // namespace webkit_media

Powered by Google App Engine
This is Rietveld 408576698