blob: b64f82b3c47c24a2494bea26f26868700cc79ee7 [file] [log] [blame]
/*
* Copyright (C) 2007, 2008, 2009 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
#if ENABLE(VIDEO)
#include "MediaPlayer.h"
#include "MediaPlayerPrivate.h"
#include "ContentType.h"
#include "IntRect.h"
#include "MIMETypeRegistry.h"
#include "FrameView.h"
#include "Frame.h"
#include "Document.h"
#include "TimeRanges.h"
#if PLATFORM(MAC)
#include "MediaPlayerPrivateQTKit.h"
#elif PLATFORM(WINCE) && !PLATFORM(QT)
#include "MediaPlayerPrivateWince.h"
#elif PLATFORM(WIN)
#include "MediaPlayerPrivateQuickTimeWin.h"
#elif PLATFORM(GTK)
#include "MediaPlayerPrivateGStreamer.h"
#elif PLATFORM(QT)
#include "MediaPlayerPrivatePhonon.h"
#elif PLATFORM(CHROMIUM)
#include "MediaPlayerPrivateChromium.h"
#elif PLATFORM(ANDROID)
#include "MediaPlayerPrivateAndroid.h"
#endif
namespace WebCore {
// a null player to make MediaPlayer logic simpler
class NullMediaPlayerPrivate : public MediaPlayerPrivateInterface {
public:
NullMediaPlayerPrivate(MediaPlayer*) { }
virtual void load(const String&) { }
virtual void cancelLoad() { }
virtual void prepareToPlay() { }
virtual void play() { }
virtual void pause() { }
virtual PlatformMedia platformMedia() const { return NoPlatformMedia; }
virtual IntSize naturalSize() const { return IntSize(0, 0); }
virtual bool hasVideo() const { return false; }
virtual bool hasAudio() const { return false; }
virtual void setVisible(bool) { }
virtual float duration() const { return 0; }
virtual float currentTime() const { return 0; }
virtual void seek(float) { }
virtual bool seeking() const { return false; }
virtual void setEndTime(float) { }
virtual void setRate(float) { }
virtual void setPreservesPitch(bool) { }
virtual bool paused() const { return false; }
virtual void setVolume(float) { }
virtual MediaPlayer::NetworkState networkState() const { return MediaPlayer::Empty; }
virtual MediaPlayer::ReadyState readyState() const { return MediaPlayer::HaveNothing; }
virtual float maxTimeSeekable() const { return 0; }
virtual PassRefPtr<TimeRanges> buffered() const { return TimeRanges::create(); }
virtual int dataRate() const { return 0; }
virtual bool totalBytesKnown() const { return false; }
virtual unsigned totalBytes() const { return 0; }
virtual unsigned bytesLoaded() const { return 0; }
virtual void setSize(const IntSize&) { }
virtual void paint(GraphicsContext*, const IntRect&) { }
virtual bool canLoadPoster() const { return false; }
virtual void setPoster(const String&) { }
#if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
virtual void deliverNotification(MediaPlayerProxyNotificationType) { }
virtual void setMediaPlayerProxy(WebMediaPlayerProxy*) { }
#endif
virtual bool hasSingleSecurityOrigin() const { return true; }
};
static MediaPlayerPrivateInterface* createNullMediaPlayer(MediaPlayer* player)
{
return new NullMediaPlayerPrivate(player);
}
// engine support
struct MediaPlayerFactory {
MediaPlayerFactory(CreateMediaEnginePlayer constructor, MediaEngineSupportedTypes getSupportedTypes, MediaEngineSupportsType supportsTypeAndCodecs)
: constructor(constructor)
, getSupportedTypes(getSupportedTypes)
, supportsTypeAndCodecs(supportsTypeAndCodecs)
{
}
CreateMediaEnginePlayer constructor;
MediaEngineSupportedTypes getSupportedTypes;
MediaEngineSupportsType supportsTypeAndCodecs;
};
static void addMediaEngine(CreateMediaEnginePlayer, MediaEngineSupportedTypes, MediaEngineSupportsType);
static MediaPlayerFactory* chooseBestEngineForTypeAndCodecs(const String& type, const String& codecs);
static Vector<MediaPlayerFactory*>& installedMediaEngines()
{
DEFINE_STATIC_LOCAL(Vector<MediaPlayerFactory*>, installedEngines, ());
static bool enginesQueried = false;
if (!enginesQueried) {
enginesQueried = true;
MediaPlayerPrivate::registerMediaEngine(addMediaEngine);
// register additional engines here
}
return installedEngines;
}
static void addMediaEngine(CreateMediaEnginePlayer constructor, MediaEngineSupportedTypes getSupportedTypes, MediaEngineSupportsType supportsType)
{
ASSERT(constructor);
ASSERT(getSupportedTypes);
ASSERT(supportsType);
installedMediaEngines().append(new MediaPlayerFactory(constructor, getSupportedTypes, supportsType));
}
static MediaPlayerFactory* chooseBestEngineForTypeAndCodecs(const String& type, const String& codecs)
{
Vector<MediaPlayerFactory*>& engines = installedMediaEngines();
if (engines.isEmpty())
return 0;
MediaPlayerFactory* engine = 0;
MediaPlayer::SupportsType supported = MediaPlayer::IsNotSupported;
unsigned count = engines.size();
for (unsigned ndx = 0; ndx < count; ndx++) {
MediaPlayer::SupportsType engineSupport = engines[ndx]->supportsTypeAndCodecs(type, codecs);
if (engineSupport > supported) {
supported = engineSupport;
engine = engines[ndx];
}
}
return engine;
}
// media player
MediaPlayer::MediaPlayer(MediaPlayerClient* client)
: m_mediaPlayerClient(client)
, m_private(createNullMediaPlayer(this))
, m_currentMediaEngine(0)
, m_frameView(0)
, m_visible(false)
, m_rate(1.0f)
, m_volume(1.0f)
, m_preservesPitch(true)
, m_autobuffer(false)
#if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
, m_playerProxy(0)
#endif
{
#if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
Vector<MediaPlayerFactory*>& engines = installedMediaEngines();
if (!engines.isEmpty()) {
m_currentMediaEngine = engines[0];
m_private.clear();
m_private.set(engines[0]->constructor(this));
}
#endif
}
MediaPlayer::~MediaPlayer()
{
}
void MediaPlayer::load(const String& url, const ContentType& contentType)
{
String type = contentType.type();
String codecs = contentType.parameter("codecs");
// if we don't know the MIME type, see if the extension can help
if (type.isEmpty() || type == "application/octet-stream" || type == "text/plain") {
int pos = url.reverseFind('.');
if (pos >= 0) {
String extension = url.substring(pos + 1);
String mediaType = MIMETypeRegistry::getMediaMIMETypeForExtension(extension);
if (!mediaType.isEmpty())
type = mediaType;
}
}
MediaPlayerFactory* engine = 0;
if (!type.isEmpty())
engine = chooseBestEngineForTypeAndCodecs(type, codecs);
// if we didn't find an engine that claims the MIME type, just use the first engine
if (!engine && !installedMediaEngines().isEmpty())
engine = installedMediaEngines()[0];
// don't delete and recreate the player unless it comes from a different engine
if (engine && m_currentMediaEngine != engine) {
m_currentMediaEngine = engine;
m_private.clear();
m_private.set(engine->constructor(this));
#if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
m_private->setMediaPlayerProxy(m_playerProxy);
#endif
}
if (m_private)
m_private->load(url);
else
m_private.set(createNullMediaPlayer(this));
}
bool MediaPlayer::canLoadPoster() const
{
return m_private->canLoadPoster();
}
void MediaPlayer::setPoster(const String& url)
{
m_private->setPoster(url);
}
void MediaPlayer::cancelLoad()
{
m_private->cancelLoad();
}
void MediaPlayer::prepareToPlay()
{
m_private->prepareToPlay();
}
void MediaPlayer::play()
{
m_private->play();
}
void MediaPlayer::pause()
{
m_private->pause();
}
float MediaPlayer::duration() const
{
return m_private->duration();
}
float MediaPlayer::startTime() const
{
return m_private->startTime();
}
float MediaPlayer::currentTime() const
{
return m_private->currentTime();
}
void MediaPlayer::seek(float time)
{
m_private->seek(time);
}
bool MediaPlayer::paused() const
{
return m_private->paused();
}
bool MediaPlayer::seeking() const
{
return m_private->seeking();
}
bool MediaPlayer::supportsFullscreen() const
{
return m_private->supportsFullscreen();
}
bool MediaPlayer::supportsSave() const
{
return m_private->supportsSave();
}
IntSize MediaPlayer::naturalSize()
{
return m_private->naturalSize();
}
bool MediaPlayer::hasVideo() const
{
return m_private->hasVideo();
}
bool MediaPlayer::hasAudio() const
{
return m_private->hasAudio();
}
bool MediaPlayer::inMediaDocument()
{
Frame* frame = m_frameView ? m_frameView->frame() : 0;
Document* document = frame ? frame->document() : 0;
return document && document->isMediaDocument();
}
PlatformMedia MediaPlayer::platformMedia() const
{
return m_private->platformMedia();
}
MediaPlayer::NetworkState MediaPlayer::networkState()
{
return m_private->networkState();
}
MediaPlayer::ReadyState MediaPlayer::readyState()
{
return m_private->readyState();
}
float MediaPlayer::volume() const
{
return m_volume;
}
void MediaPlayer::setVolume(float volume)
{
m_volume = volume;
m_private->setVolume(volume);
}
float MediaPlayer::rate() const
{
return m_rate;
}
void MediaPlayer::setRate(float rate)
{
m_rate = rate;
m_private->setRate(rate);
}
bool MediaPlayer::preservesPitch() const
{
return m_preservesPitch;
}
void MediaPlayer::setPreservesPitch(bool preservesPitch)
{
m_preservesPitch = preservesPitch;
m_private->setPreservesPitch(preservesPitch);
}
int MediaPlayer::dataRate() const
{
return m_private->dataRate();
}
void MediaPlayer::setEndTime(float time)
{
m_private->setEndTime(time);
}
PassRefPtr<TimeRanges> MediaPlayer::buffered()
{
return m_private->buffered();
}
float MediaPlayer::maxTimeSeekable()
{
return m_private->maxTimeSeekable();
}
unsigned MediaPlayer::bytesLoaded()
{
return m_private->bytesLoaded();
}
bool MediaPlayer::totalBytesKnown()
{
return m_private->totalBytesKnown();
}
unsigned MediaPlayer::totalBytes()
{
return m_private->totalBytes();
}
void MediaPlayer::setSize(const IntSize& size)
{
m_size = size;
m_private->setSize(size);
}
bool MediaPlayer::visible() const
{
return m_visible;
}
void MediaPlayer::setVisible(bool b)
{
m_visible = b;
m_private->setVisible(b);
}
bool MediaPlayer::autobuffer() const
{
return m_autobuffer;
}
void MediaPlayer::setAutobuffer(bool b)
{
if (m_autobuffer != b) {
m_autobuffer = b;
m_private->setAutobuffer(b);
}
}
void MediaPlayer::paint(GraphicsContext* p, const IntRect& r)
{
m_private->paint(p, r);
}
void MediaPlayer::paintCurrentFrameInContext(GraphicsContext* p, const IntRect& r)
{
m_private->paintCurrentFrameInContext(p, r);
}
MediaPlayer::SupportsType MediaPlayer::supportsType(ContentType contentType)
{
String type = contentType.type();
String codecs = contentType.parameter("codecs");
MediaPlayerFactory* engine = chooseBestEngineForTypeAndCodecs(type, codecs);
if (!engine)
return IsNotSupported;
return engine->supportsTypeAndCodecs(type, codecs);
}
void MediaPlayer::getSupportedTypes(HashSet<String>& types)
{
Vector<MediaPlayerFactory*>& engines = installedMediaEngines();
if (engines.isEmpty())
return;
unsigned count = engines.size();
for (unsigned ndx = 0; ndx < count; ndx++)
engines[ndx]->getSupportedTypes(types);
}
bool MediaPlayer::isAvailable()
{
return !installedMediaEngines().isEmpty();
}
#if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
void MediaPlayer::deliverNotification(MediaPlayerProxyNotificationType notification)
{
m_private->deliverNotification(notification);
}
void MediaPlayer::setMediaPlayerProxy(WebMediaPlayerProxy* proxy)
{
m_playerProxy = proxy;
m_private->setMediaPlayerProxy(proxy);
}
#endif
#if USE(ACCELERATED_COMPOSITING)
void MediaPlayer::acceleratedRenderingStateChanged()
{
m_private->acceleratedRenderingStateChanged();
}
bool MediaPlayer::supportsAcceleratedRendering() const
{
return m_private->supportsAcceleratedRendering();
}
#endif // USE(ACCELERATED_COMPOSITING)
bool MediaPlayer::hasSingleSecurityOrigin() const
{
return m_private->hasSingleSecurityOrigin();
}
MediaPlayer::MovieLoadType MediaPlayer::movieLoadType() const
{
return m_private->movieLoadType();
}
// Client callbacks.
void MediaPlayer::networkStateChanged()
{
if (m_mediaPlayerClient)
m_mediaPlayerClient->mediaPlayerNetworkStateChanged(this);
}
void MediaPlayer::readyStateChanged()
{
if (m_mediaPlayerClient)
m_mediaPlayerClient->mediaPlayerReadyStateChanged(this);
}
void MediaPlayer::volumeChanged()
{
if (m_mediaPlayerClient)
m_mediaPlayerClient->mediaPlayerVolumeChanged(this);
}
void MediaPlayer::timeChanged()
{
if (m_mediaPlayerClient)
m_mediaPlayerClient->mediaPlayerTimeChanged(this);
}
void MediaPlayer::sizeChanged()
{
if (m_mediaPlayerClient)
m_mediaPlayerClient->mediaPlayerSizeChanged(this);
}
void MediaPlayer::repaint()
{
if (m_mediaPlayerClient)
m_mediaPlayerClient->mediaPlayerRepaint(this);
}
void MediaPlayer::durationChanged()
{
if (m_mediaPlayerClient)
m_mediaPlayerClient->mediaPlayerDurationChanged(this);
}
void MediaPlayer::rateChanged()
{
if (m_mediaPlayerClient)
m_mediaPlayerClient->mediaPlayerRateChanged(this);
}
}
#endif