1// Copyright (c) 2009 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 "config.h"
6#include "WebMediaPlayerClientImpl.h"
7
8#if ENABLE(VIDEO)
9
10#include "Frame.h"
11#include "GraphicsContext.h"
12#include "HTMLMediaElement.h"
13#include "IntSize.h"
14#include "KURL.h"
15#include "MediaPlayer.h"
16#include "NotImplemented.h"
17#include "RenderView.h"
18#include "TimeRanges.h"
19#include "VideoLayerChromium.h"
20
21#if USE(ACCELERATED_COMPOSITING)
22#include "RenderLayerCompositor.h"
23#endif
24
25#include "VideoFrameChromium.h"
26#include "VideoFrameChromiumImpl.h"
27#include "WebCanvas.h"
28#include "WebCString.h"
29#include "WebFrameClient.h"
30#include "WebFrameImpl.h"
31#include "WebKit.h"
32#include "WebKitClient.h"
33#include "WebMediaElement.h"
34#include "WebMediaPlayer.h"
35#include "WebMimeRegistry.h"
36#include "WebRect.h"
37#include "WebSize.h"
38#include "WebString.h"
39#include "WebURL.h"
40#include "WebViewImpl.h"
41
42// WebCommon.h defines WEBKIT_USING_SKIA so this has to be included last.
43#if WEBKIT_USING_SKIA
44#include "PlatformContextSkia.h"
45#endif
46
47#include <wtf/Assertions.h>
48#include <wtf/text/CString.h>
49
50using namespace WebCore;
51
52namespace WebKit {
53
54static WebMediaPlayer* createWebMediaPlayer(
55    WebMediaPlayerClient* client, Frame* frame)
56{
57    WebFrameImpl* webFrame = WebFrameImpl::fromFrame(frame);
58
59    if (!webFrame->client())
60        return 0;
61    return webFrame->client()->createMediaPlayer(webFrame, client);
62}
63
64bool WebMediaPlayerClientImpl::m_isEnabled = false;
65
66bool WebMediaPlayerClientImpl::isEnabled()
67{
68    return m_isEnabled;
69}
70
71void WebMediaPlayerClientImpl::setIsEnabled(bool isEnabled)
72{
73    m_isEnabled = isEnabled;
74}
75
76void WebMediaPlayerClientImpl::registerSelf(MediaEngineRegistrar registrar)
77{
78    if (m_isEnabled) {
79        registrar(WebMediaPlayerClientImpl::create,
80                  WebMediaPlayerClientImpl::getSupportedTypes,
81                  WebMediaPlayerClientImpl::supportsType,
82                  0,
83                  0,
84                  0);
85    }
86}
87
88WebMediaPlayerClientImpl* WebMediaPlayerClientImpl::fromMediaElement(const WebMediaElement* element)
89{
90    PlatformMedia pm = element->constUnwrap<HTMLMediaElement>()->platformMedia();
91    return static_cast<WebMediaPlayerClientImpl*>(pm.media.chromiumMediaPlayer);
92}
93
94WebMediaPlayer* WebMediaPlayerClientImpl::mediaPlayer() const
95{
96    return m_webMediaPlayer.get();
97}
98
99// WebMediaPlayerClient --------------------------------------------------------
100
101WebMediaPlayerClientImpl::~WebMediaPlayerClientImpl()
102{
103    // VideoLayerChromium may outlive this object so make sure all frames are
104    // released.
105#if USE(ACCELERATED_COMPOSITING)
106    if (m_videoLayer.get())
107        m_videoLayer->releaseCurrentFrame();
108#endif
109}
110
111void WebMediaPlayerClientImpl::networkStateChanged()
112{
113    ASSERT(m_mediaPlayer);
114    m_mediaPlayer->networkStateChanged();
115}
116
117void WebMediaPlayerClientImpl::readyStateChanged()
118{
119    ASSERT(m_mediaPlayer);
120    m_mediaPlayer->readyStateChanged();
121#if USE(ACCELERATED_COMPOSITING)
122    if (hasVideo() && supportsAcceleratedRendering() && !m_videoLayer.get())
123        m_videoLayer = VideoLayerChromium::create(0, this);
124#endif
125}
126
127void WebMediaPlayerClientImpl::volumeChanged(float newVolume)
128{
129    ASSERT(m_mediaPlayer);
130    m_mediaPlayer->volumeChanged(newVolume);
131}
132
133void WebMediaPlayerClientImpl::muteChanged(bool newMute)
134{
135    ASSERT(m_mediaPlayer);
136    m_mediaPlayer->muteChanged(newMute);
137}
138
139void WebMediaPlayerClientImpl::timeChanged()
140{
141    ASSERT(m_mediaPlayer);
142    m_mediaPlayer->timeChanged();
143}
144
145void WebMediaPlayerClientImpl::repaint()
146{
147    ASSERT(m_mediaPlayer);
148#if USE(ACCELERATED_COMPOSITING)
149    if (m_videoLayer.get() && supportsAcceleratedRendering())
150        m_videoLayer->setNeedsDisplay(IntRect(0, 0, m_videoLayer->bounds().width(), m_videoLayer->bounds().height()));
151#endif
152    m_mediaPlayer->repaint();
153}
154
155void WebMediaPlayerClientImpl::durationChanged()
156{
157    ASSERT(m_mediaPlayer);
158    m_mediaPlayer->durationChanged();
159}
160
161void WebMediaPlayerClientImpl::rateChanged()
162{
163    ASSERT(m_mediaPlayer);
164    m_mediaPlayer->rateChanged();
165}
166
167void WebMediaPlayerClientImpl::sizeChanged()
168{
169    ASSERT(m_mediaPlayer);
170    m_mediaPlayer->sizeChanged();
171}
172
173void WebMediaPlayerClientImpl::sawUnsupportedTracks()
174{
175    ASSERT(m_mediaPlayer);
176    m_mediaPlayer->mediaPlayerClient()->mediaPlayerSawUnsupportedTracks(m_mediaPlayer);
177}
178
179float WebMediaPlayerClientImpl::volume() const
180{
181    if (m_mediaPlayer)
182        return m_mediaPlayer->volume();
183    return 0.0f;
184}
185
186void WebMediaPlayerClientImpl::playbackStateChanged()
187{
188    ASSERT(m_mediaPlayer);
189    m_mediaPlayer->playbackStateChanged();
190}
191
192WebMediaPlayer::Preload WebMediaPlayerClientImpl::preload() const
193{
194    if (m_mediaPlayer)
195        return static_cast<WebMediaPlayer::Preload>(m_mediaPlayer->preload());
196    return static_cast<WebMediaPlayer::Preload>(m_preload);
197}
198
199// MediaPlayerPrivateInterface -------------------------------------------------
200
201void WebMediaPlayerClientImpl::load(const String& url)
202{
203    m_url = url;
204
205    // Video frame object is owned by WebMediaPlayer. Before destroying
206    // WebMediaPlayer all frames need to be released.
207#if USE(ACCELERATED_COMPOSITING)
208    if (m_videoLayer.get())
209        m_videoLayer->releaseCurrentFrame();
210#endif
211
212    if (m_preload == MediaPlayer::None) {
213        m_webMediaPlayer.clear();
214        m_delayingLoad = true;
215    } else
216        loadInternal();
217}
218
219void WebMediaPlayerClientImpl::loadInternal()
220{
221    Frame* frame = static_cast<HTMLMediaElement*>(m_mediaPlayer->mediaPlayerClient())->document()->frame();
222    m_webMediaPlayer.set(createWebMediaPlayer(this, frame));
223    if (m_webMediaPlayer.get())
224        m_webMediaPlayer->load(KURL(ParsedURLString, m_url));
225}
226
227void WebMediaPlayerClientImpl::cancelLoad()
228{
229    if (m_webMediaPlayer.get())
230        m_webMediaPlayer->cancelLoad();
231}
232
233#if USE(ACCELERATED_COMPOSITING)
234PlatformLayer* WebMediaPlayerClientImpl::platformLayer() const
235{
236    ASSERT(m_supportsAcceleratedCompositing);
237    return m_videoLayer.get();
238}
239#endif
240
241PlatformMedia WebMediaPlayerClientImpl::platformMedia() const
242{
243    PlatformMedia pm;
244    pm.type = PlatformMedia::ChromiumMediaPlayerType;
245    pm.media.chromiumMediaPlayer = const_cast<WebMediaPlayerClientImpl*>(this);
246    return pm;
247}
248
249void WebMediaPlayerClientImpl::play()
250{
251    if (m_webMediaPlayer.get())
252        m_webMediaPlayer->play();
253}
254
255void WebMediaPlayerClientImpl::pause()
256{
257    if (m_webMediaPlayer.get())
258        m_webMediaPlayer->pause();
259}
260
261void WebMediaPlayerClientImpl::prepareToPlay()
262{
263    if (m_delayingLoad)
264        startDelayedLoad();
265}
266
267IntSize WebMediaPlayerClientImpl::naturalSize() const
268{
269    if (m_webMediaPlayer.get())
270        return m_webMediaPlayer->naturalSize();
271    return IntSize();
272}
273
274bool WebMediaPlayerClientImpl::hasVideo() const
275{
276    if (m_webMediaPlayer.get())
277        return m_webMediaPlayer->hasVideo();
278    return false;
279}
280
281bool WebMediaPlayerClientImpl::hasAudio() const
282{
283    if (m_webMediaPlayer.get())
284        return m_webMediaPlayer->hasAudio();
285    return false;
286}
287
288void WebMediaPlayerClientImpl::setVisible(bool visible)
289{
290    if (m_webMediaPlayer.get())
291        m_webMediaPlayer->setVisible(visible);
292}
293
294float WebMediaPlayerClientImpl::duration() const
295{
296    if (m_webMediaPlayer.get())
297        return m_webMediaPlayer->duration();
298    return 0.0f;
299}
300
301float WebMediaPlayerClientImpl::currentTime() const
302{
303    if (m_webMediaPlayer.get())
304        return m_webMediaPlayer->currentTime();
305    return 0.0f;
306}
307
308void WebMediaPlayerClientImpl::seek(float time)
309{
310    if (m_webMediaPlayer.get())
311        m_webMediaPlayer->seek(time);
312}
313
314bool WebMediaPlayerClientImpl::seeking() const
315{
316    if (m_webMediaPlayer.get())
317        return m_webMediaPlayer->seeking();
318    return false;
319}
320
321void WebMediaPlayerClientImpl::setEndTime(float time)
322{
323    if (m_webMediaPlayer.get())
324        m_webMediaPlayer->setEndTime(time);
325}
326
327void WebMediaPlayerClientImpl::setRate(float rate)
328{
329    if (m_webMediaPlayer.get())
330        m_webMediaPlayer->setRate(rate);
331}
332
333bool WebMediaPlayerClientImpl::paused() const
334{
335    if (m_webMediaPlayer.get())
336        return m_webMediaPlayer->paused();
337    return false;
338}
339
340bool WebMediaPlayerClientImpl::supportsFullscreen() const
341{
342    if (m_webMediaPlayer.get())
343        return m_webMediaPlayer->supportsFullscreen();
344    return false;
345}
346
347bool WebMediaPlayerClientImpl::supportsSave() const
348{
349    if (m_webMediaPlayer.get())
350        return m_webMediaPlayer->supportsSave();
351    return false;
352}
353
354void WebMediaPlayerClientImpl::setVolume(float volume)
355{
356    if (m_webMediaPlayer.get())
357        m_webMediaPlayer->setVolume(volume);
358}
359
360MediaPlayer::NetworkState WebMediaPlayerClientImpl::networkState() const
361{
362    if (m_webMediaPlayer.get())
363        return static_cast<MediaPlayer::NetworkState>(m_webMediaPlayer->networkState());
364    return MediaPlayer::Empty;
365}
366
367MediaPlayer::ReadyState WebMediaPlayerClientImpl::readyState() const
368{
369    if (m_webMediaPlayer.get())
370        return static_cast<MediaPlayer::ReadyState>(m_webMediaPlayer->readyState());
371    return MediaPlayer::HaveNothing;
372}
373
374float WebMediaPlayerClientImpl::maxTimeSeekable() const
375{
376    if (m_webMediaPlayer.get())
377        return m_webMediaPlayer->maxTimeSeekable();
378    return 0.0f;
379}
380
381PassRefPtr<TimeRanges> WebMediaPlayerClientImpl::buffered() const
382{
383    if (m_webMediaPlayer.get()) {
384        const WebTimeRanges& webRanges = m_webMediaPlayer->buffered();
385
386        // FIXME: Save the time ranges in a member variable and update it when needed.
387        RefPtr<TimeRanges> ranges = TimeRanges::create();
388        for (size_t i = 0; i < webRanges.size(); ++i)
389            ranges->add(webRanges[i].start, webRanges[i].end);
390        return ranges.release();
391    }
392    return TimeRanges::create();
393}
394
395int WebMediaPlayerClientImpl::dataRate() const
396{
397    if (m_webMediaPlayer.get())
398        return m_webMediaPlayer->dataRate();
399    return 0;
400}
401
402bool WebMediaPlayerClientImpl::totalBytesKnown() const
403{
404    if (m_webMediaPlayer.get())
405        return m_webMediaPlayer->totalBytesKnown();
406    return false;
407}
408
409unsigned WebMediaPlayerClientImpl::totalBytes() const
410{
411    if (m_webMediaPlayer.get())
412        return static_cast<unsigned>(m_webMediaPlayer->totalBytes());
413    return 0;
414}
415
416unsigned WebMediaPlayerClientImpl::bytesLoaded() const
417{
418    if (m_webMediaPlayer.get())
419        return static_cast<unsigned>(m_webMediaPlayer->bytesLoaded());
420    return 0;
421}
422
423void WebMediaPlayerClientImpl::setSize(const IntSize& size)
424{
425    if (m_webMediaPlayer.get())
426        m_webMediaPlayer->setSize(WebSize(size.width(), size.height()));
427}
428
429void WebMediaPlayerClientImpl::paint(GraphicsContext* context, const IntRect& rect)
430{
431#if USE(ACCELERATED_COMPOSITING)
432    // If we are using GPU to render video, ignore requests to paint frames into
433    // canvas because it will be taken care of by VideoLayerChromium.
434    if (acceleratedRenderingInUse())
435        return;
436#endif
437    paintCurrentFrameInContext(context, rect);
438}
439
440void WebMediaPlayerClientImpl::paintCurrentFrameInContext(GraphicsContext* context, const IntRect& rect)
441{
442    // Normally GraphicsContext operations do nothing when painting is disabled.
443    // Since we're accessing platformContext() directly we have to manually
444    // check.
445    if (m_webMediaPlayer.get() && !context->paintingDisabled()) {
446#if WEBKIT_USING_SKIA
447        PlatformGraphicsContext* platformContext = context->platformContext();
448        WebCanvas* canvas = platformContext->canvas();
449
450        canvas->saveLayerAlpha(0, platformContext->getNormalizedAlpha());
451
452        m_webMediaPlayer->paint(canvas, rect);
453
454        canvas->restore();
455#elif WEBKIT_USING_CG
456        m_webMediaPlayer->paint(context->platformContext(), rect);
457#else
458        notImplemented();
459#endif
460    }
461}
462
463void WebMediaPlayerClientImpl::setPreload(MediaPlayer::Preload preload)
464{
465    m_preload = preload;
466
467    if (m_webMediaPlayer.get())
468        m_webMediaPlayer->setPreload(static_cast<WebMediaPlayer::Preload>(preload));
469
470    if (m_delayingLoad && m_preload != MediaPlayer::None)
471        startDelayedLoad();
472}
473
474bool WebMediaPlayerClientImpl::hasSingleSecurityOrigin() const
475{
476    if (m_webMediaPlayer.get())
477        return m_webMediaPlayer->hasSingleSecurityOrigin();
478    return false;
479}
480
481MediaPlayer::MovieLoadType WebMediaPlayerClientImpl::movieLoadType() const
482{
483    if (m_webMediaPlayer.get())
484        return static_cast<MediaPlayer::MovieLoadType>(
485            m_webMediaPlayer->movieLoadType());
486    return MediaPlayer::Unknown;
487}
488
489unsigned WebMediaPlayerClientImpl::decodedFrameCount() const
490{
491    if (m_webMediaPlayer.get())
492        return m_webMediaPlayer->decodedFrameCount();
493    return 0;
494}
495
496unsigned WebMediaPlayerClientImpl::droppedFrameCount() const
497{
498    if (m_webMediaPlayer.get())
499        return m_webMediaPlayer->droppedFrameCount();
500    return 0;
501}
502
503unsigned WebMediaPlayerClientImpl::audioDecodedByteCount() const
504{
505    if (m_webMediaPlayer.get())
506        return m_webMediaPlayer->audioDecodedByteCount();
507    return 0;
508}
509
510unsigned WebMediaPlayerClientImpl::videoDecodedByteCount() const
511{
512    if (m_webMediaPlayer.get())
513        return m_webMediaPlayer->videoDecodedByteCount();
514    return 0;
515}
516
517#if USE(ACCELERATED_COMPOSITING)
518bool WebMediaPlayerClientImpl::supportsAcceleratedRendering() const
519{
520    return m_supportsAcceleratedCompositing;
521}
522
523bool WebMediaPlayerClientImpl::acceleratedRenderingInUse()
524{
525    return m_videoLayer.get() && m_videoLayer->layerRenderer();
526}
527
528VideoFrameChromium* WebMediaPlayerClientImpl::getCurrentFrame()
529{
530    VideoFrameChromium* videoFrame = 0;
531    if (m_webMediaPlayer.get()) {
532        WebVideoFrame* webkitVideoFrame = m_webMediaPlayer->getCurrentFrame();
533        if (webkitVideoFrame)
534            videoFrame = new VideoFrameChromiumImpl(webkitVideoFrame);
535    }
536    return videoFrame;
537}
538
539void WebMediaPlayerClientImpl::putCurrentFrame(VideoFrameChromium* videoFrame)
540{
541    if (videoFrame) {
542        if (m_webMediaPlayer.get()) {
543            m_webMediaPlayer->putCurrentFrame(
544                VideoFrameChromiumImpl::toWebVideoFrame(videoFrame));
545        }
546        delete videoFrame;
547    }
548}
549#endif
550
551MediaPlayerPrivateInterface* WebMediaPlayerClientImpl::create(MediaPlayer* player)
552{
553    WebMediaPlayerClientImpl* client = new WebMediaPlayerClientImpl();
554    client->m_mediaPlayer = player;
555
556#if USE(ACCELERATED_COMPOSITING)
557    Frame* frame = static_cast<HTMLMediaElement*>(
558        client->m_mediaPlayer->mediaPlayerClient())->document()->frame();
559
560    // This does not actually check whether the hardware can support accelerated
561    // compositing, but only if the flag is set. However, this is checked lazily
562    // in WebViewImpl::setIsAcceleratedCompositingActive() and will fail there
563    // if necessary.
564    client->m_supportsAcceleratedCompositing =
565        frame->contentRenderer()->compositor()->hasAcceleratedCompositing();
566#endif
567
568    return client;
569}
570
571void WebMediaPlayerClientImpl::getSupportedTypes(HashSet<String>& supportedTypes)
572{
573    // FIXME: integrate this list with WebMediaPlayerClientImpl::supportsType.
574    notImplemented();
575}
576
577MediaPlayer::SupportsType WebMediaPlayerClientImpl::supportsType(const String& type,
578                                                                 const String& codecs)
579{
580    WebMimeRegistry::SupportsType supportsType =
581        webKitClient()->mimeRegistry()->supportsMediaMIMEType(type, codecs);
582
583    switch (supportsType) {
584    default:
585        ASSERT_NOT_REACHED();
586    case WebMimeRegistry::IsNotSupported:
587        return MediaPlayer::IsNotSupported;
588    case WebMimeRegistry::IsSupported:
589        return MediaPlayer::IsSupported;
590    case WebMimeRegistry::MayBeSupported:
591        return MediaPlayer::MayBeSupported;
592    }
593    return MediaPlayer::IsNotSupported;
594}
595
596void WebMediaPlayerClientImpl::startDelayedLoad()
597{
598    ASSERT(m_delayingLoad);
599    ASSERT(!m_webMediaPlayer.get());
600
601    m_delayingLoad = false;
602
603    loadInternal();
604}
605
606WebMediaPlayerClientImpl::WebMediaPlayerClientImpl()
607    : m_mediaPlayer(0)
608    , m_delayingLoad(false)
609    , m_preload(MediaPlayer::MetaData)
610#if USE(ACCELERATED_COMPOSITING)
611    , m_videoLayer(0)
612    , m_supportsAcceleratedCompositing(false)
613#endif
614{
615}
616
617} // namespace WebKit
618
619#endif  // ENABLE(VIDEO)
620