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

Side by Side 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "webkit/media/android/webmediaplayer_android.h"
6
7 #include <string>
8
9 #include "base/bind.h"
10 #include "base/command_line.h"
11 #include "base/file_path.h"
12 #include "base/logging.h"
13 #include "base/utf_string_conversions.h"
14 #include "media/base/android/media_player_bridge.h"
15 #include "net/base/mime_util.h"
16 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h"
17 #include "third_party/WebKit/Source/WebKit/chromium/public/WebMediaPlayerClient. h"
18 #include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h"
19 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebCookieJar .h"
20 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebRect.h"
21 #include "webkit/media/android/webmediaplayer_proxy_android.h"
22 #include "webkit/media/webvideoframe_impl.h"
23
24 using WebKit::WebCanvas;
25 using WebKit::WebFrame;
26 using WebKit::WebMediaPlayerClient;
27 using WebKit::WebMediaPlayer;
28 using WebKit::WebRect;
29 using WebKit::WebSize;
30 using WebKit::WebTimeRanges;
31 using WebKit::WebURL;
32 using WebKit::WebVideoFrame;
33 using media::MediaPlayerBridge;
34 using media::VideoFrame;
35 using webkit_media::WebVideoFrameImpl;
36
37 namespace {
38
39 // Platform independent method for converting and rounding floating point
40 // seconds to an int64 timestamp.
41 //
42 // Refer to https://bugs.webkit.org/show_bug.cgi?id=52697 for details.
43 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
44 float microseconds = seconds * base::Time::kMicrosecondsPerSecond;
45 float integer = ceilf(microseconds);
46 float difference = integer - microseconds;
47
48 // Round down if difference is large enough.
49 if ((microseconds > 0 && difference > 0.5f) ||
50 (microseconds <= 0 && difference >= 0.5f)) {
51 integer -= 1.0f;
52 }
53
54 // Now we can safely cast to int64 microseconds.
55 return base::TimeDelta::FromMicroseconds(static_cast<int64>(integer));
56 }
57
58 } // namespace
59
60 namespace webkit_media {
61
62 bool WebMediaPlayerAndroid::incognito_mode_ = false;
63
64 WebMediaPlayerAndroid::WebMediaPlayerAndroid(
65 WebFrame* frame,
66 WebMediaPlayerClient* client,
67 WebKit::WebCookieJar* cookie_jar)
68 : 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
69 client_(client),
70 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.
71 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.
72 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.
73 proxy_(new WebMediaPlayerProxyAndroid(render_message_loop_)),
74 prepared_(false),
75 duration_(0),
76 time_to_seek_(0),
77 seeking_(false),
78 current_time_(0),
79 buffered_bytes_(0),
80 cookie_jar_(cookie_jar),
81 pending_play_event_(false),
82 skip_loading_(false),
83 network_state_(WebMediaPlayer::Empty),
84 ready_state_(WebMediaPlayer::HaveNothing) {
85 video_frame_.reset(new WebVideoFrameImpl(VideoFrame::CreateEmptyFrame()));
86 }
87
88 WebMediaPlayerAndroid::~WebMediaPlayerAndroid() {
89 proxy_->SetWebMediaPlayer(NULL);
90
91 if (media_player_.get()) {
92 media_player_->Stop();
93 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.
94 }
95
96 video_frame_.reset(NULL);
scherkus (not reviewing) 2012/04/17 03:57:31 ditto
qinmin 2012/04/18 20:06:30 Done.
97 }
98
99 void WebMediaPlayerAndroid::InitIncognito(bool incognito_mode) {
100 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
101 }
102
103 void WebMediaPlayerAndroid::load(const WebURL& url) {
104 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.
105 GURL gurl(url_);
106
107 // Calling LoadUrl will cause android mediaplayer to start buffering and
108 // decoding the data. On mobile devices, this costs a lot of data usage
109 // and could even introduce performance issues. So we don't load the url
110 // unless it is a local file. We will start loading the media only when
111 // 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
112 if (gurl.SchemeIs("file"))
113 LoadUrl(url_);
114 else
115 skip_loading_ = true;
116
117 UpdateNetworkState(WebMediaPlayer::Loading);
118 UpdateReadyState(WebMediaPlayer::HaveNothing);
119
120 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
121 // 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.
122 // Android does not provide any function to do that.
123 // Set the initial duration value to 100 seconds so that user can touch
124 // the seek bar to perform seek. We will scale the seek position later
125 // when we got the actual duration.
126 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
127
128 // Pretend everything has been loaded so that webkit can
129 // still call play() and seek().
130 UpdateReadyState(WebMediaPlayer::HaveMetadata);
131 UpdateReadyState(WebMediaPlayer::HaveEnoughData);
132 }
133 }
134
135 void WebMediaPlayerAndroid::cancelLoad() {
136 NOTIMPLEMENTED();
137 }
138
139 void WebMediaPlayerAndroid::play() {
140 if (media_player_.get()) {
141 if (!prepared_)
142 pending_play_event_ = true;
143 else
144 PlayInternal();
145 } else {
146 pending_play_event_ = true;
147 LoadUrl(url_);
148 }
149 }
150
151 void WebMediaPlayerAndroid::pause() {
152 if (media_player_.get()) {
153 if (!prepared_)
154 pending_play_event_ = false;
155 else
156 PauseInternal();
157 } else {
158 // 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.
159 pending_play_event_ = false;
160 }
161 }
162
163 void WebMediaPlayerAndroid::seek(float seconds) {
164 // Record the time to seek when OnMediaPrepared() is called.
165 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.
166 if (media_player_.get()) {
167 if (prepared_)
168 SeekInternal(seconds);
169 } else
170 LoadUrl(url_);
scherkus (not reviewing) 2012/04/17 03:57:31 curly braces please
qinmin 2012/04/18 20:06:30 Done.
171 }
172
173 bool WebMediaPlayerAndroid::supportsFullscreen() const {
174 return true;
175 }
176
177 bool WebMediaPlayerAndroid::supportsSave() const {
178 return false;
179 }
180
181 void WebMediaPlayerAndroid::setEndTime(float seconds) {
182 // 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
183 }
184
185 void WebMediaPlayerAndroid::setRate(float rate) {
186 NOTIMPLEMENTED();
187 }
188
189 void WebMediaPlayerAndroid::setVolume(float volume) {
190 media_player_->SetVolume(volume, volume);
191 }
192
193 void WebMediaPlayerAndroid::setVisible(bool visible) {
194 // Deprecated.
195 }
196
197 bool WebMediaPlayerAndroid::totalBytesKnown() {
198 NOTIMPLEMENTED();
199 return false;
200 }
201
202 bool WebMediaPlayerAndroid::hasVideo() const {
203 // FIXME(qinmin): need a better method to determine whether the current media
204 // content contains video. Android does not provide any function to do
205 // this.
206 // We don't know whether the current media content has video unless
207 // the player is prepared. If the player is not prepared, we fall back
208 // to the mime-type. There may be no mime-type on a redirect URL.
209 // In that case, we conservatively assume it contains video so that
210 // enterfullscreen call will not fail.
211 if (!prepared_) {
212 GURL gurl(url_);
213 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.
214 return false;
215 std::string mime;
216 if(!net::GetMimeTypeFromFile(FilePath(gurl.path()), &mime))
217 return true;
218 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
219 }
220
221 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.
222 }
223
224 bool WebMediaPlayerAndroid::hasAudio() const {
225 // TODO(hclam): Query status of audio and return the actual value.
226 return true;
227 }
228
229 bool WebMediaPlayerAndroid::paused() const {
230 if (!prepared_)
231 return !pending_play_event_;
232 return !media_player_->IsPlaying();
233 }
234
235 bool WebMediaPlayerAndroid::seeking() const {
236 return seeking_;
237 }
238
239 float WebMediaPlayerAndroid::duration() const {
240 return duration_;
241 }
242
243 float WebMediaPlayerAndroid::currentTime() const {
244 // If the player is pending for a seek, return the seek time.
245 if (!prepared_ || seeking())
246 return time_to_seek_;
247
248 // When playback is about to finish, android media player often stops
249 // at a time which is smaller than the duration. This makes webkit never
250 // know that the playback has finished. To solve this, we set the
251 // 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.
252 // received. And return the greater of the two values so that the current
253 // time is most updated.
254 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
255 (float) media_player_->GetCurrentTime().InSecondsF());
scherkus (not reviewing) 2012/04/17 03:57:31 static_cast<>
qinmin 2012/04/18 20:06:30 Done.
256 }
257
258 int WebMediaPlayerAndroid::dataRate() const {
259 // Deprecated.
260 return 0;
261 }
262
263 WebSize WebMediaPlayerAndroid::naturalSize() const {
264 return natural_size_;
265 }
266
267 WebMediaPlayer::NetworkState WebMediaPlayerAndroid::networkState() const {
268 return network_state_;
269 }
270
271 WebMediaPlayer::ReadyState WebMediaPlayerAndroid::readyState() const {
272 return ready_state_;
273 }
274
275 const WebTimeRanges& WebMediaPlayerAndroid::buffered() {
276 return time_ranges_;
277 }
278
279 float WebMediaPlayerAndroid::maxTimeSeekable() const {
280 // TODO(hclam): If this stream is not seekable this should return 0.
281 return duration();
282 }
283
284 unsigned long long WebMediaPlayerAndroid::bytesLoaded() const {
285 return buffered_bytes_;
286 }
287
288 unsigned long long WebMediaPlayerAndroid::totalBytes() const {
289 // Deprecated.
290 return 0;
291 }
292
293 void WebMediaPlayerAndroid::setSize(const WebSize& size) {
294 texture_size_ = size;
295 }
296
297 void WebMediaPlayerAndroid::paint(WebCanvas* canvas, const WebRect& rect) {
298 NOTIMPLEMENTED();
299 }
300
301 bool WebMediaPlayerAndroid::hasSingleSecurityOrigin() const {
302 return false;
303 }
304
305 WebMediaPlayer::MovieLoadType
306 WebMediaPlayerAndroid::movieLoadType() const {
307 // Deprecated.
308 return WebMediaPlayer::Unknown;
309 }
310
311 float WebMediaPlayerAndroid::mediaTimeForTimeValue(float timeValue) const {
312 return ConvertSecondsToTimestamp(timeValue).InSecondsF();
313 }
314
315 unsigned WebMediaPlayerAndroid::decodedFrameCount() const {
316 NOTIMPLEMENTED();
317 return 0;
318 }
319
320 unsigned WebMediaPlayerAndroid::droppedFrameCount() const {
321 NOTIMPLEMENTED();
322 return 0;
323 }
324
325 unsigned WebMediaPlayerAndroid::audioDecodedByteCount() const {
326 NOTIMPLEMENTED();
327 return 0;
328 }
329
330 unsigned WebMediaPlayerAndroid::videoDecodedByteCount() const {
331 NOTIMPLEMENTED();
332 return 0;
333 }
334
335 void WebMediaPlayerAndroid::OnMediaPrepared() {
336 WebKit::WebTimeRanges new_buffered(static_cast<size_t>(1));
337 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.
338 new_buffered[0].end = 0.0f;
339 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
340 prepared_ = true;
341
342 // Update the media duration first so that webkit will get the correct
343 // duration when UpdateReadyState is called.
344 float dur = duration_;
345 duration_ = media_player_->GetDuration().InSecondsF();
346
347 GURL gurl(url_);
348 if (gurl.SchemeIs("file"))
349 UpdateNetworkState(WebMediaPlayer::Loaded);
350
351 if (ready_state_ != WebMediaPlayer::HaveEnoughData) {
352 UpdateReadyState(WebMediaPlayer::HaveMetadata);
353 UpdateReadyState(WebMediaPlayer::HaveEnoughData);
354 } else {
355 // If the status is already set to HaveEnoughData, set it again to make sure
356 // that Videolayerchromium will get created.
357 UpdateReadyState(WebMediaPlayer::HaveEnoughData);
358 }
359
360 if (skip_loading_) {
361 // In we have skipped loading, the duration was preset to 100 sec.
362 // 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
363 if (duration_ != dur) {
364 // Scale the time_to_seek_ according to the new duration.
365 time_to_seek_ = time_to_seek_ * duration_ / 100.0f;
366 client_->durationChanged();
367 }
368 }
369
370 // If media player was recovered from a saved state, consume all the pending
371 // events.
372 seek(time_to_seek_);
373
374 if (pending_play_event_)
375 PlayInternal();
376
377 pending_play_event_ = false;
378 }
379
380 void WebMediaPlayerAndroid::OnPlaybackComplete() {
381 // Set the current time equal to duration to let webkit know that play back
382 // is completed.
383 current_time_ = duration();
384 client_->timeChanged();
385 }
386
387 void WebMediaPlayerAndroid::OnBufferingUpdate(int percentage) {
388 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
389 time_ranges_[0].end = duration() * percentage / 100;
390 // Implement a trick here to fake progress event, as WebKit checks
391 // consecutive bytesLoaded() to see if any progress made.
392 // See HTMLMediaElement::progressEventTimerFired.
393 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
394 }
395 }
396
397 void WebMediaPlayerAndroid::OnSeekComplete() {
398 seeking_ = false;
399
400 UpdateReadyState(WebMediaPlayer::HaveEnoughData);
401
402 client_->timeChanged();
403 }
404
405 void WebMediaPlayerAndroid::OnMediaError(int error_type) {
406 switch (error_type) {
407 case MediaPlayerBridge::MEDIA_ERROR_UNKNOWN:
408 // 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.
409 // As WebKit uses FormatError to indicate an error for bogus URL or bad
410 // 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.
411 UpdateNetworkState(WebMediaPlayer::FormatError);
412 break;
413 case MediaPlayerBridge::MEDIA_ERROR_SERVER_DIED:
414 // TODO(zhenghao): Media server died. In this case, the application must
415 // release the MediaPlayer object and instantiate a new one.
416 UpdateNetworkState(WebMediaPlayer::DecodeError);
417 break;
418 case MediaPlayerBridge::MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK:
419 UpdateNetworkState(WebMediaPlayer::FormatError);
420 break;
421 case MediaPlayerBridge::MEDIA_ERROR_INVALID_CODE:
422 break;
423 }
424 client_->repaint();
425 }
426
427 void WebMediaPlayerAndroid::OnMediaInfo(int info_type) {
428 NOTIMPLEMENTED();
429 }
430
431 void WebMediaPlayerAndroid::OnVideoSizeChanged(int width, int height) {
432 natural_size_.width = width;
433 natural_size_.height = height;
434 }
435
436 void WebMediaPlayerAndroid::UpdateNetworkState(
437 WebMediaPlayer::NetworkState state) {
438 network_state_ = state;
439 client_->networkStateChanged();
440 }
441
442 void WebMediaPlayerAndroid::UpdateReadyState(
443 WebMediaPlayer::ReadyState state) {
444 ready_state_ = state;
445 client_->readyStateChanged();
446 }
447
448 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.
449 jobject j_surface) {
450 if (media_player_.get())
451 media_player_->SetVideoSurface(j_surface);
452 }
453
454 void WebMediaPlayerAndroid::InitializeMediaPlayer() {
455 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
456 prepared_ = false;
457 media_player_.reset(new MediaPlayerBridge());
458 media_player_->SetStayAwakeWhilePlaying();
459 proxy_->SetWebMediaPlayer(this);
460 }
461 }
462
463 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
464 if (!media_player_.get())
465 InitializeMediaPlayer();
466
467 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.
468
469 std::string cookies;
470 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
471 cookies = UTF16ToUTF8(cookie_jar_->cookies(url, url));
472 media_player_->SetDataSource(url.spec(), cookies, incognito_mode_);
473
474 media_player_->Prepare(
475 base::Bind(&WebMediaPlayerProxyAndroid::MediaInfoCallback, proxy_),
476 base::Bind(&WebMediaPlayerProxyAndroid::MediaErrorCallback, proxy_),
477 base::Bind(&WebMediaPlayerProxyAndroid::VideoSizeChangedCallback, proxy_),
478 base::Bind(&WebMediaPlayerProxyAndroid::BufferingUpdateCallback, proxy_),
479 base::Bind(&WebMediaPlayerProxyAndroid::MediaPreparedCallback, proxy_));
480
scherkus (not reviewing) 2012/04/17 03:57:31 nit: remove blank line
qinmin 2012/04/18 20:06:30 Done.
481 }
482
483 void WebMediaPlayerAndroid::PlayInternal() {
484 CHECK(prepared_);
485
486 if (paused())
487 media_player_->Start(base::Bind(
488 &WebMediaPlayerProxyAndroid::PlaybackCompleteCallback, proxy_));
489 }
490
491 void WebMediaPlayerAndroid::PauseInternal() {
492 CHECK(prepared_);
493 media_player_->Pause();
494 }
495
496 void WebMediaPlayerAndroid::SeekInternal(float seconds) {
497 CHECK(prepared_);
498 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
499 client_->timeChanged();
500 return;
501 }
502 seeking_ = true;
503 media_player_->SeekTo(ConvertSecondsToTimestamp(seconds), base::Bind(
504 &WebMediaPlayerProxyAndroid::SeekCompleteCallback, proxy_));
505 }
506
507 // -------------------------------------------------------------------------
508 // Methods that are called on the compositor thread if useThreadedCompositor
509 // 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.
510 WebVideoFrame* WebMediaPlayerAndroid::getCurrentFrame() {
511 return video_frame_.get();
512 }
513
514 void WebMediaPlayerAndroid::putCurrentFrame(
515 WebVideoFrame* web_video_frame) {
516 }
517
518 // -------------------------------------------------------------------------
519
520 } // namespace webkit_media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698