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

Side by Side Diff: webkit/media/webmediaplayer_ms.cc

Issue 10918052: create a separate WebMediaPlayer for URL derived from media stream (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: fix win build Created 8 years, 3 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
Property Changes:
Added: svn:eol-style
+ LF
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/webmediaplayer_ms.h"
6
7 #include <limits>
8
9 #include "base/bind.h"
10 #include "base/callback.h"
11 #include "base/metrics/histogram.h"
12 #include "media/base/media_log.h"
13 #include "media/base/video_frame.h"
14 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h"
15 #include "third_party/WebKit/Source/WebKit/chromium/public/WebMediaPlayerClient. h"
16 #include "third_party/WebKit/Source/WebKit/chromium/public/WebVideoFrame.h"
17 #include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h"
18 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebRect.h"
19 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebSize.h"
20 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebURL.h"
21 #include "v8/include/v8.h"
22 #include "webkit/media/media_stream_client.h"
23 #include "webkit/media/video_frame_provider.h"
24 #include "webkit/media/webmediaplayer_delegate.h"
25 #include "webkit/media/webmediaplayer_util.h"
26 #include "webkit/media/webvideoframe_impl.h"
27
28 using WebKit::WebCanvas;
29 using WebKit::WebMediaPlayer;
30 using WebKit::WebRect;
31 using WebKit::WebSize;
32
33 namespace {
34
35 // Amount of extra memory used by each player instance reported to V8.
36 // It is not exact number -- first, it differs on different platforms,
37 // and second, it is very hard to calculate. Instead, use some arbitrary
38 // value that will cause garbage collection from time to time. We don't want
39 // it to happen on every allocation, but don't want 5k players to sit in memory
40 // either. Looks that chosen constant achieves both goals, at least for audio
41 // objects. (Do not worry about video objects yet, JS programs do not create
42 // thousands of them...)
43 const int kPlayerExtraMemory = 1024 * 1024;
44
45 } // namespace
46
47 namespace webkit_media {
48
49 WebMediaPlayerMS::WebMediaPlayerMS(
50 WebKit::WebFrame* frame,
51 WebKit::WebMediaPlayerClient* client,
52 base::WeakPtr<WebMediaPlayerDelegate> delegate,
53 MediaStreamClient* media_stream_client,
54 media::MediaLog* media_log)
55 : frame_(frame),
56 network_state_(WebMediaPlayer::NetworkStateEmpty),
57 ready_state_(WebMediaPlayer::ReadyStateHaveNothing),
58 buffered_(static_cast<size_t>(1)),
59 main_loop_(MessageLoop::current()),
scherkus (not reviewing) 2012/09/07 11:44:03 You don't need this member variable as you're only
wjia(left Chromium) 2012/09/13 01:22:07 Done.
60 client_(client),
61 delegate_(delegate),
62 media_stream_client_(media_stream_client),
63 video_frame_provider_started_(false),
64 paused_(true),
65 pending_repaint_(false),
66 got_first_frame_(false),
67 total_frame_count_(0),
68 dropped_frame_count_(0),
69 media_log_(media_log),
70 accelerated_compositing_reported_(false),
71 incremented_externally_allocated_memory_(false) {
72 DVLOG(1) << "WebMediaPlayerMS::ctor";
73 DCHECK(media_stream_client);
74 media_log_->AddEvent(
scherkus (not reviewing) 2012/09/07 11:44:03 this will end up on chrome://media-internals but I
wjia(left Chromium) 2012/09/13 01:22:07 I'd keep it for now.
75 media_log_->CreateEvent(media::MediaLogEvent::WEBMEDIAPLAYER_CREATED));
76
77 // Let V8 know we started new thread if we did not did it yet.
78 // Made separate task to avoid deletion of player currently being created.
79 // Also, delaying GC until after player starts gets rid of starting lag --
80 // collection happens in parallel with playing.
81 //
82 // TODO(enal): remove when we get rid of per-audio-stream thread.
83 MessageLoop::current()->PostTask(
84 FROM_HERE,
85 base::Bind(&WebMediaPlayerMS::IncrementExternallyAllocatedMemory,
86 AsWeakPtr()));
87
88 // Also we want to be notified of |main_loop_| destruction.
89 main_loop_->AddDestructionObserver(this);
scherkus (not reviewing) 2012/09/07 11:44:03 I don't think you need a destruction observer as y
wjia(left Chromium) 2012/09/13 01:22:07 Done.
90 }
91
92 WebMediaPlayerMS::~WebMediaPlayerMS() {
93 DVLOG(1) << "WebMediaPlayerMS::dtor";
94 DCHECK_EQ(main_loop_, MessageLoop::current());
95 Destroy();
96 media_log_->AddEvent(
97 media_log_->CreateEvent(media::MediaLogEvent::WEBMEDIAPLAYER_DESTROYED));
98
99 if (delegate_)
100 delegate_->PlayerGone(this);
101
102 // Finally tell the |main_loop_| we don't want to be notified of destruction
103 // event.
104 if (main_loop_) {
105 main_loop_->RemoveDestructionObserver(this);
106 }
107 }
108
109 void WebMediaPlayerMS::load(const WebKit::WebURL& url, CORSMode cors_mode) {
110 DVLOG(1) << "WebMediaPlayerMS::load";
111 DCHECK_EQ(main_loop_, MessageLoop::current());
112
113 GURL gurl(url);
114
115 setVolume(GetClient()->volume());
116 SetNetworkState(WebMediaPlayer::NetworkStateLoading);
117 SetReadyState(WebMediaPlayer::ReadyStateHaveNothing);
118 media_log_->AddEvent(media_log_->CreateLoadEvent(url.spec()));
119
120 // Check if this url is media stream.
121 video_frame_provider_ = media_stream_client_->GetVideoFrameProvider(
122 url,
123 base::Bind(&WebMediaPlayerMS::OnSourceError, AsWeakPtr()),
124 base::Bind(&WebMediaPlayerMS::Repaint, AsWeakPtr()));
125 if (video_frame_provider_) {
126 SetNetworkState(WebMediaPlayer::NetworkStateLoaded);
127 GetClient()->sourceOpened();
128 GetClient()->setOpaque(true);
129 SetReadyState(WebMediaPlayer::ReadyStateHaveMetadata);
130 SetReadyState(WebMediaPlayer::ReadyStateHaveEnoughData);
131 RepaintInternal();
132 } else {
133 SetNetworkState(WebMediaPlayer::NetworkStateNetworkError);
134 }
135 }
136
137 void WebMediaPlayerMS::cancelLoad() {
138 DCHECK_EQ(main_loop_, MessageLoop::current());
139 }
140
141 void WebMediaPlayerMS::play() {
142 DVLOG(1) << "WebMediaPlayerMS::play";
143 DCHECK_EQ(main_loop_, MessageLoop::current());
144
145 paused_ = false;
146 if (video_frame_provider_) {
147 if (video_frame_provider_started_) {
148 video_frame_provider_->Play();
149 } else {
150 video_frame_provider_started_ = true;
151 video_frame_provider_->Start();
152 }
153 }
154 // TODO: add audio.
scherkus (not reviewing) 2012/09/07 11:44:03 TODO(wjia)? is there a bug filed for WebRTC audio
wjia(left Chromium) 2012/09/13 01:22:07 Done. I'd use the same bug for adding WebRTC audio
155
156 media_log_->AddEvent(media_log_->CreateEvent(media::MediaLogEvent::PLAY));
157
158 if (delegate_)
159 delegate_->DidPlay(this);
160 }
161
162 void WebMediaPlayerMS::pause() {
163 DVLOG(1) << "WebMediaPlayerMS::pause";
164 DCHECK_EQ(main_loop_, MessageLoop::current());
165
166 if (video_frame_provider_)
167 video_frame_provider_->Pause();
168 // TODO: add audio.
scherkus (not reviewing) 2012/09/07 11:44:03 ditto
wjia(left Chromium) 2012/09/13 01:22:07 Done.
169 paused_ = true;
170
171 media_log_->AddEvent(media_log_->CreateEvent(media::MediaLogEvent::PAUSE));
172
173 if (delegate_)
174 delegate_->DidPause(this);
175 }
176
177 bool WebMediaPlayerMS::supportsFullscreen() const {
178 DCHECK_EQ(main_loop_, MessageLoop::current());
179 return true;
180 }
181
182 bool WebMediaPlayerMS::supportsSave() const {
183 DCHECK_EQ(main_loop_, MessageLoop::current());
184 return false;
185 }
186
187 void WebMediaPlayerMS::seek(float seconds) {
188 DCHECK_EQ(main_loop_, MessageLoop::current());
189 }
190
191 void WebMediaPlayerMS::setEndTime(float seconds) {
192 DCHECK_EQ(main_loop_, MessageLoop::current());
193 }
194
195 void WebMediaPlayerMS::setRate(float rate) {
196 DCHECK_EQ(main_loop_, MessageLoop::current());
197 }
198
199 void WebMediaPlayerMS::setVolume(float volume) {
200 DCHECK_EQ(main_loop_, MessageLoop::current());
201 // TODO: set audio volume.
scherkus (not reviewing) 2012/09/07 11:44:03 TODO(wjia)? NOTIMPLEMENTED?
wjia(left Chromium) 2012/09/13 01:22:07 Done.
202 }
203
204 void WebMediaPlayerMS::setVisible(bool visible) {
205 DCHECK_EQ(main_loop_, MessageLoop::current());
206 }
207
208 void WebMediaPlayerMS::setPreload(WebMediaPlayer::Preload preload) {
209 DCHECK_EQ(main_loop_, MessageLoop::current());
210 }
211
212 bool WebMediaPlayerMS::totalBytesKnown() {
213 DCHECK_EQ(main_loop_, MessageLoop::current());
214 return false;
215 }
216
217 bool WebMediaPlayerMS::hasVideo() const {
218 DCHECK_EQ(main_loop_, MessageLoop::current());
219 return !!video_frame_provider_;
scherkus (not reviewing) 2012/09/07 11:44:03 use != NULL
wjia(left Chromium) 2012/09/13 01:22:07 Done.
220 }
221
222 bool WebMediaPlayerMS::hasAudio() const {
223 DCHECK_EQ(main_loop_, MessageLoop::current());
224 // TODO: add audio support.
scherkus (not reviewing) 2012/09/07 11:44:03 TODO(wjia)?
wjia(left Chromium) 2012/09/13 01:22:07 Done.
225 return false;
226 }
227
228 WebKit::WebSize WebMediaPlayerMS::naturalSize() const {
229 DCHECK_EQ(main_loop_, MessageLoop::current());
230
231 gfx::Size size;
232 if (current_frame_)
233 size = current_frame_->natural_size();
234 DVLOG(1) << "WebMediaPlayerMS::naturalSize, " << size.ToString();
235 return WebKit::WebSize(size);
236 }
237
238 bool WebMediaPlayerMS::paused() const {
239 DCHECK_EQ(main_loop_, MessageLoop::current());
240 return paused_;
241 }
242
243 bool WebMediaPlayerMS::seeking() const {
244 DCHECK_EQ(main_loop_, MessageLoop::current());
245 return false;
246 }
247
248 float WebMediaPlayerMS::duration() const {
249 DCHECK_EQ(main_loop_, MessageLoop::current());
250 return std::numeric_limits<float>::infinity();
251 }
252
253 float WebMediaPlayerMS::currentTime() const {
254 DCHECK_EQ(main_loop_, MessageLoop::current());
255 base::TimeDelta current_time;
256 if (current_frame_.get()) {
scherkus (not reviewing) 2012/09/07 11:44:03 how about: if (current_frame_.get()) return cur
wjia(left Chromium) 2012/09/13 01:22:07 Done.
257 current_time = current_frame_->GetTimestamp();
258 }
259 return static_cast<float>(current_time.InSecondsF());
260 }
261
262 int WebMediaPlayerMS::dataRate() const {
263 DCHECK_EQ(main_loop_, MessageLoop::current());
264 return 0;
265 }
266
267 WebMediaPlayer::NetworkState WebMediaPlayerMS::networkState() const {
268 DCHECK_EQ(main_loop_, MessageLoop::current());
269 DVLOG(1) << "WebMediaPlayerMS::networkState, state:" << network_state_;
270 return network_state_;
271 }
272
273 WebMediaPlayer::ReadyState WebMediaPlayerMS::readyState() const {
274 DCHECK_EQ(main_loop_, MessageLoop::current());
275 DVLOG(1) << "WebMediaPlayerMS::readyState, state:" << ready_state_;
276 return ready_state_;
277 }
278
279 const WebKit::WebTimeRanges& WebMediaPlayerMS::buffered() {
280 DCHECK_EQ(main_loop_, MessageLoop::current());
281 return buffered_;
scherkus (not reviewing) 2012/09/07 11:44:03 you don't need this variable -- just alloc + retur
wjia(left Chromium) 2012/09/13 01:22:07 This variable has to be here. If a WebTimeRanges i
scherkus (not reviewing) 2012/09/13 10:22:43 ah didn't see the const-ref return value
282 }
283
284 float WebMediaPlayerMS::maxTimeSeekable() const {
285 DCHECK_EQ(main_loop_, MessageLoop::current());
286 return 0.0f;
287 }
288
289 bool WebMediaPlayerMS::didLoadingProgress() const {
290 DCHECK_EQ(main_loop_, MessageLoop::current());
291 return false;
292 }
293
294 unsigned long long WebMediaPlayerMS::totalBytes() const {
295 DCHECK_EQ(main_loop_, MessageLoop::current());
296 return 0;
297 }
298
299 void WebMediaPlayerMS::setSize(const WebSize& size) {
300 DCHECK_EQ(main_loop_, MessageLoop::current());
301 // Don't need to do anything as we use the dimensions passed in via paint().
302 }
303
304 void WebMediaPlayerMS::paint(WebCanvas* canvas,
305 const WebRect& rect,
306 uint8_t alpha) {
307 DVLOG(1) << "WebMediaPlayerMS::paint";
308 DCHECK_EQ(main_loop_, MessageLoop::current());
309
310 if (!accelerated_compositing_reported_) {
311 accelerated_compositing_reported_ = true;
312 // Normally paint() is only called in non-accelerated rendering, but there
313 // are exceptions such as webgl where compositing is used in the WebView but
314 // video frames are still rendered to a canvas.
315 UMA_HISTOGRAM_BOOLEAN(
316 "Media.AcceleratedCompositingActive",
317 frame_->view()->isAcceleratedCompositingActive());
318 }
319
320 video_renderer_.Paint(current_frame_, canvas, rect, alpha);
321 }
322
323 bool WebMediaPlayerMS::hasSingleSecurityOrigin() const {
324 DCHECK_EQ(main_loop_, MessageLoop::current());
325 return true;
326 }
327
328 bool WebMediaPlayerMS::didPassCORSAccessCheck() const {
329 DCHECK_EQ(main_loop_, MessageLoop::current());
330 return true;
331 }
332
333 WebMediaPlayer::MovieLoadType WebMediaPlayerMS::movieLoadType() const {
334 DCHECK_EQ(main_loop_, MessageLoop::current());
335 return WebMediaPlayer::MovieLoadTypeUnknown;
336 }
337
338 float WebMediaPlayerMS::mediaTimeForTimeValue(float timeValue) const {
339 return ConvertSecondsToTimestamp(timeValue).InSecondsF();
340 }
341
342 unsigned WebMediaPlayerMS::decodedFrameCount() const {
343 DCHECK_EQ(main_loop_, MessageLoop::current());
344 DVLOG(1) << "WebMediaPlayerMS::decodedFrameCount, " << total_frame_count_;
345 return total_frame_count_;
346 }
347
348 unsigned WebMediaPlayerMS::droppedFrameCount() const {
349 DCHECK_EQ(main_loop_, MessageLoop::current());
350 DVLOG(1) << "WebMediaPlayerMS::droppedFrameCount, " << dropped_frame_count_;
351 return dropped_frame_count_;
352 }
353
354 unsigned WebMediaPlayerMS::audioDecodedByteCount() const {
355 DCHECK_EQ(main_loop_, MessageLoop::current());
356 NOTIMPLEMENTED();
357 return 0;
358 }
359
360 unsigned WebMediaPlayerMS::videoDecodedByteCount() const {
361 DCHECK_EQ(main_loop_, MessageLoop::current());
362 NOTIMPLEMENTED();
363 return 0;
364 }
365
366 WebKit::WebVideoFrame* WebMediaPlayerMS::getCurrentFrame() {
367 DVLOG(1) << "WebMediaPlayerMS::getCurrentFrame";
368 DCHECK_EQ(main_loop_, MessageLoop::current());
369 DCHECK(!pending_repaint_);
370 pending_repaint_ = true;
scherkus (not reviewing) 2012/09/07 11:44:03 this seems odd -- what exactly is pending_repaint_
wjia(left Chromium) 2012/09/13 01:22:07 |pending_repaint_| is used to ensure client->repai
371 if (current_frame_.get())
372 return new webkit_media::WebVideoFrameImpl(current_frame_);
373 return NULL;
374 }
375
376 void WebMediaPlayerMS::putCurrentFrame(
377 WebKit::WebVideoFrame* web_video_frame) {
378 DVLOG(1) << "WebMediaPlayerMS::putCurrentFrame";
379 DCHECK_EQ(main_loop_, MessageLoop::current());
380 DCHECK(pending_repaint_);
381 pending_repaint_ = false;
382 if (!accelerated_compositing_reported_) {
383 accelerated_compositing_reported_ = true;
384 UMA_HISTOGRAM_BOOLEAN("Media.AcceleratedCompositingActive",
385 frame_->view()->isAcceleratedCompositingActive());
386 }
387 if (web_video_frame) {
388 delete web_video_frame;
389 }
390 }
391
392 void WebMediaPlayerMS::WillDestroyCurrentMessageLoop() {
393 Destroy();
394 main_loop_ = NULL;
395 }
396
397 void WebMediaPlayerMS::Repaint(const scoped_refptr<media::VideoFrame>& frame) {
398 DVLOG(1) << "WebMediaPlayerMS::Repaint with frame";
399 DCHECK_EQ(main_loop_, MessageLoop::current());
400 ++total_frame_count_;
401 if (!got_first_frame_) {
402 got_first_frame_ = true;
403 start_time_ = frame->GetTimestamp();
404 }
405 current_frame_ = frame;
406 current_frame_->SetTimestamp(frame->GetTimestamp() - start_time_);
407 if (pending_repaint_) {
scherkus (not reviewing) 2012/09/07 11:44:03 considering you only set this in the HW decode pat
wjia(left Chromium) 2012/09/13 01:22:07 Removed dropped_frame_count_ for now. Is it possib
scherkus (not reviewing) 2012/09/13 10:22:43 I wouldn't say the two are mutually exclusive -- f
408 ++dropped_frame_count_;
409 } else {
410 GetClient()->repaint();
411 }
412 }
413
414 void WebMediaPlayerMS::RepaintInternal() {
415 DVLOG(1) << "WebMediaPlayerMS::Repaint";
416 DCHECK_EQ(main_loop_, MessageLoop::current());
417 if (!pending_repaint_) {
418 GetClient()->repaint();
419 }
420 }
421
422 void WebMediaPlayerMS::OnSourceError() {
423 DVLOG(1) << "WebMediaPlayerMS::OnSourceError";
424 DCHECK_EQ(main_loop_, MessageLoop::current());
425 SetNetworkState(WebMediaPlayer::NetworkStateFormatError);
426 RepaintInternal();
427 }
428
429 void WebMediaPlayerMS::SetNetworkState(WebMediaPlayer::NetworkState state) {
430 DCHECK_EQ(main_loop_, MessageLoop::current());
431 network_state_ = state;
432 // Always notify to ensure client has the latest value.
433 GetClient()->networkStateChanged();
434 }
435
436 void WebMediaPlayerMS::SetReadyState(WebMediaPlayer::ReadyState state) {
437 DCHECK_EQ(main_loop_, MessageLoop::current());
438 ready_state_ = state;
439 // Always notify to ensure client has the latest value.
440 GetClient()->readyStateChanged();
441 }
442
443 void WebMediaPlayerMS::Destroy() {
444 DCHECK_EQ(main_loop_, MessageLoop::current());
445
446 if (video_frame_provider_) {
447 video_frame_provider_->Stop();
scherkus (not reviewing) 2012/09/07 11:44:03 considering Stop() is synchronous how about replac
wjia(left Chromium) 2012/09/13 01:22:07 That won't work for LocalVideoCapture, since Start
scherkus (not reviewing) 2012/09/13 10:22:43 Let's see if I can untangle this a bit... VideoFr
wjia(left Chromium) 2012/09/19 03:22:06 Please see my comments in local_video_capture.cc a
448 }
449
450 // Let V8 know we are not using extra resources anymore.
451 if (incremented_externally_allocated_memory_) {
452 v8::V8::AdjustAmountOfExternalAllocatedMemory(-kPlayerExtraMemory);
453 incremented_externally_allocated_memory_ = false;
454 }
455 }
456
457 WebKit::WebMediaPlayerClient* WebMediaPlayerMS::GetClient() {
458 DCHECK_EQ(main_loop_, MessageLoop::current());
459 DCHECK(client_);
460 return client_;
461 }
462
463 void WebMediaPlayerMS::IncrementExternallyAllocatedMemory() {
464 DCHECK_EQ(main_loop_, MessageLoop::current());
465 incremented_externally_allocated_memory_ = true;
466 v8::V8::AdjustAmountOfExternalAllocatedMemory(kPlayerExtraMemory);
467 }
468
469 } // namespace webkit_media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698