Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- From 234a24a13099540dffafea33d3983327fe4e1c8c Mon Sep 17 00:00:00 2001
- From: Danilo Cesar Lemes de Paula <danilo.cesar@collabora.co.uk>
- Date: Tue, 19 Jun 2012 14:13:14 -0300
- Subject: [PATCH] Adding new mediaPlayer
- ---
- Source/WebCore/platform/graphics/MediaPlayer.cpp | 104 +++-
- Source/WebCore/platform/graphics/MediaPlayer.h | 10 +-
- .../gstreamer/MediaPlayerPrivateGStreamer.cpp | 15 +
- .../gstreamer/MediaPlayerPrivateGStreamer.h | 3 +
- .../StreamMediaPlayerPrivateGStreamer.cpp | 622 ++++++++++++++++++++
- .../gstreamer/StreamMediaPlayerPrivateGStreamer.h | 153 +++++
- 6 files changed, 902 insertions(+), 5 deletions(-)
- create mode 100644 Source/WebCore/platform/graphics/gstreamer/StreamMediaPlayerPrivateGStreamer.cpp
- create mode 100644 Source/WebCore/platform/graphics/gstreamer/StreamMediaPlayerPrivateGStreamer.h
- diff --git a/Source/WebCore/platform/graphics/MediaPlayer.cpp b/Source/WebCore/platform/graphics/MediaPlayer.cpp
- index 7d845ac..e746b88 100644
- --- a/Source/WebCore/platform/graphics/MediaPlayer.cpp
- +++ b/Source/WebCore/platform/graphics/MediaPlayer.cpp
- @@ -46,6 +46,9 @@
- #if USE(GSTREAMER)
- #include "MediaPlayerPrivateGStreamer.h"
- +#if ENABLE(MEDIA_STREAM)
- +#include "StreamMediaPlayerPrivateGStreamer.h"
- +#endif
- #define PlatformMediaEngineClassName MediaPlayerPrivateGStreamer
- #endif
- @@ -175,29 +178,54 @@ static PassOwnPtr<MediaPlayerPrivateInterface> createNullMediaPlayer(MediaPlayer
- struct MediaPlayerFactory {
- WTF_MAKE_NONCOPYABLE(MediaPlayerFactory); WTF_MAKE_FAST_ALLOCATED;
- public:
- +#if ENABLE(MEDIA_STREAM)
- + MediaPlayerFactory(CreateMediaEnginePlayer constructor, MediaEngineSupportedTypes getSupportedTypes, MediaEngineSupportsType supportsTypeAndCodecs, MediaEngineSupportsProtocol supportsProtocol,
- + MediaEngineGetSitesInMediaCache getSitesInMediaCache, MediaEngineClearMediaCache clearMediaCache, MediaEngineClearMediaCacheForSite clearMediaCacheForSite)
- + : constructor(constructor)
- + , getSupportedTypes(getSupportedTypes)
- + , supportsTypeAndCodecs(supportsTypeAndCodecs)
- + , supportsProtocol(supportsProtocol)
- + , getSitesInMediaCache(getSitesInMediaCache)
- + , clearMediaCache(clearMediaCache)
- + , clearMediaCacheForSite(clearMediaCacheForSite)
- + {
- + }
- +#else
- MediaPlayerFactory(CreateMediaEnginePlayer constructor, MediaEngineSupportedTypes getSupportedTypes, MediaEngineSupportsType supportsTypeAndCodecs,
- - MediaEngineGetSitesInMediaCache getSitesInMediaCache, MediaEngineClearMediaCache clearMediaCache, MediaEngineClearMediaCacheForSite clearMediaCacheForSite)
- + MediaEngineGetSitesInMediaCache getSitesInMediaCache, MediaEngineClearMediaCache clearMediaCache, MediaEngineClearMediaCacheForSite clearMediaCacheForSite)
- : constructor(constructor)
- , getSupportedTypes(getSupportedTypes)
- , supportsTypeAndCodecs(supportsTypeAndCodecs)
- , getSitesInMediaCache(getSitesInMediaCache)
- , clearMediaCache(clearMediaCache)
- , clearMediaCacheForSite(clearMediaCacheForSite)
- -
- {
- }
- +#endif
- CreateMediaEnginePlayer constructor;
- MediaEngineSupportedTypes getSupportedTypes;
- MediaEngineSupportsType supportsTypeAndCodecs;
- +#if ENABLE(MEDIA_STREAM)
- + MediaEngineSupportsProtocol supportsProtocol;
- +#endif
- MediaEngineGetSitesInMediaCache getSitesInMediaCache;
- MediaEngineClearMediaCache clearMediaCache;
- MediaEngineClearMediaCacheForSite clearMediaCacheForSite;
- };
- +#if ENABLE(MEDIA_STREAM)
- +static void addMediaEngine(CreateMediaEnginePlayer, MediaEngineSupportedTypes, MediaEngineSupportsType, MediaEngineSupportsProtocol, MediaEngineGetSitesInMediaCache, MediaEngineClearMediaCache, MediaEngineClearMediaCacheForSite);
- +#else
- static void addMediaEngine(CreateMediaEnginePlayer, MediaEngineSupportedTypes, MediaEngineSupportsType, MediaEngineGetSitesInMediaCache, MediaEngineClearMediaCache, MediaEngineClearMediaCacheForSite);
- +#endif
- +
- static MediaPlayerFactory* bestMediaEngineForTypeAndCodecs(const String& type, const String& codecs, const String& keySystem, MediaPlayerFactory* current = 0);
- +#if ENABLE(MEDIA_STREAM)
- +static MediaPlayerFactory* bestMediaEngineForProtocolAndTypeAndCodecs(const String& type, const String& codecs, const String& keySystem, const String &protocol, MediaPlayerFactory* current = 0);
- +#else
- static MediaPlayerFactory* nextMediaEngine(MediaPlayerFactory* current);
- +#endif
- static Vector<MediaPlayerFactory*>& installedMediaEngines()
- {
- @@ -207,6 +235,10 @@ static Vector<MediaPlayerFactory*>& installedMediaEngines()
- if (!enginesQueried) {
- enginesQueried = true;
- +#if USE(GSTREAMER) && ENABLE(MEDIA_STREAM)
- + StreamMediaPlayerPrivateGStreamer::registerMediaEngine(addMediaEngine);
- +#endif
- +
- #if USE(AVFOUNDATION)
- if (Settings::isAVFoundationEnabled()) {
- #if PLATFORM(MAC)
- @@ -225,6 +257,19 @@ static Vector<MediaPlayerFactory*>& installedMediaEngines()
- return installedEngines;
- }
- +
- +#if ENABLE(MEDIA_STREAM)
- +static void addMediaEngine(CreateMediaEnginePlayer constructor, MediaEngineSupportedTypes getSupportedTypes, MediaEngineSupportsType supportsType, MediaEngineSupportsProtocol supportsProtocol,
- + MediaEngineGetSitesInMediaCache getSitesInMediaCache, MediaEngineClearMediaCache clearMediaCache, MediaEngineClearMediaCacheForSite clearMediaCacheForSite)
- +{
- + ASSERT(constructor);
- + ASSERT(getSupportedTypes);
- + ASSERT(supportsType);
- + ASSERT(supportsProtocol);
- +
- + installedMediaEngines().append(new MediaPlayerFactory(constructor, getSupportedTypes, supportsType, supportsProtocol, getSitesInMediaCache, clearMediaCache, clearMediaCacheForSite));
- +}
- +#else
- static void addMediaEngine(CreateMediaEnginePlayer constructor, MediaEngineSupportedTypes getSupportedTypes, MediaEngineSupportsType supportsType,
- MediaEngineGetSitesInMediaCache getSitesInMediaCache, MediaEngineClearMediaCache clearMediaCache, MediaEngineClearMediaCacheForSite clearMediaCacheForSite)
- {
- @@ -234,6 +279,7 @@ static void addMediaEngine(CreateMediaEnginePlayer constructor, MediaEngineSuppo
- installedMediaEngines().append(new MediaPlayerFactory(constructor, getSupportedTypes, supportsType, getSitesInMediaCache, clearMediaCache, clearMediaCacheForSite));
- }
- +#endif
- static const AtomicString& applicationOctetStream()
- {
- @@ -295,6 +341,51 @@ static MediaPlayerFactory* bestMediaEngineForTypeAndCodecs(const String& type, c
- return engine;
- }
- +#if ENABLE(MEDIA_STREAM)
- +static MediaPlayerFactory* bestMediaEngineForProtocolAndTypeAndCodecs(const String& type, const String& codecs, const String& keySystem, const String &url, MediaPlayerFactory* current)
- +{
- + Vector<MediaPlayerFactory*>& engines = installedMediaEngines();
- + if (engines.isEmpty())
- + return 0;
- +
- + // 4.8.10.3 MIME types - In the absence of a specification to the contrary, the MIME type "application/octet-stream"
- + // when used with parameters, e.g. "application/octet-stream;codecs=theora", is a type that the user agent knows
- + // it cannot render.
- + if (type == applicationOctetStream()) {
- + if (!codecs.isEmpty())
- + return 0;
- + }
- +
- + MediaPlayerFactory* engine = 0;
- + MediaPlayer::SupportsType supported = MediaPlayer::IsNotSupported;
- + unsigned count = engines.size();
- + for (unsigned ndx = 0; ndx < count; ndx++) {
- + if (current) {
- + if (current == engines[ndx])
- + current = 0;
- + continue;
- + }
- + if (engines[ndx]->supportsProtocol(url) == MediaPlayer::IsSupported) {
- + supported = MediaPlayer::IsSupported;
- + engine = engines[ndx];
- + } else {
- +#if ENABLE(ENCRYPTED_MEDIA)
- + MediaPlayer::SupportsType engineSupport = engines[ndx]->supportsTypeAndCodecs(type, codecs, keySystem);
- +#else
- + UNUSED_PARAM(keySystem);
- + ASSERT(keySystem.isEmpty());
- + MediaPlayer::SupportsType engineSupport = engines[ndx]->supportsTypeAndCodecs(type, codecs);
- +#endif
- + if (engineSupport > supported) {
- + supported = engineSupport;
- + engine = engines[ndx];
- + }
- + }
- + }
- +
- + return engine;
- +}
- +#else
- static MediaPlayerFactory* nextMediaEngine(MediaPlayerFactory* current)
- {
- Vector<MediaPlayerFactory*>& engines = installedMediaEngines();
- @@ -310,6 +401,7 @@ static MediaPlayerFactory* nextMediaEngine(MediaPlayerFactory* current)
- return engines[currentIndex + 1];
- }
- +#endif
- // media player
- @@ -382,12 +474,18 @@ void MediaPlayer::loadWithNextMediaEngine(MediaPlayerFactory* current)
- {
- MediaPlayerFactory* engine = 0;
- + LOG (MediaStream, "=========== content type %s", m_contentMIMEType.utf8().data());
- +
- +#if ENABLE(MEDIA_STREAM)
- + engine = bestMediaEngineForProtocolAndTypeAndCodecs(m_contentMIMEType, m_contentTypeCodecs, m_keySystem, m_url, current);
- +#else
- if (!m_contentMIMEType.isEmpty())
- engine = bestMediaEngineForTypeAndCodecs(m_contentMIMEType, m_contentTypeCodecs, m_keySystem, current);
- // If no MIME type is specified or the type was inferred from the file extension, just use the next engine.
- if (!engine && (m_contentMIMEType.isEmpty() || m_contentMIMETypeWasInferredFromExtension))
- engine = nextMediaEngine(current);
- +#endif
- // Don't delete and recreate the player unless it comes from a different engine.
- if (!engine) {
- @@ -418,7 +516,7 @@ void MediaPlayer::loadWithNextMediaEngine(MediaPlayerFactory* current)
- m_mediaPlayerClient->mediaPlayerResourceNotSupported(this);
- }
- }
- -}
- +}
- bool MediaPlayer::hasAvailableVideoFrame() const
- {
- diff --git a/Source/WebCore/platform/graphics/MediaPlayer.h b/Source/WebCore/platform/graphics/MediaPlayer.h
- index 6c722a0..e6d0658 100644
- --- a/Source/WebCore/platform/graphics/MediaPlayer.h
- +++ b/Source/WebCore/platform/graphics/MediaPlayer.h
- @@ -431,9 +431,15 @@ typedef void (*MediaEngineGetSitesInMediaCache)(Vector<String>&);
- typedef void (*MediaEngineClearMediaCache)();
- typedef void (*MediaEngineClearMediaCacheForSite)(const String&);
- -typedef void (*MediaEngineRegistrar)(CreateMediaEnginePlayer, MediaEngineSupportedTypes, MediaEngineSupportsType,
- - MediaEngineGetSitesInMediaCache, MediaEngineClearMediaCache, MediaEngineClearMediaCacheForSite);
- +#if ENABLE(MEDIA_STREAM)
- +typedef MediaPlayer::SupportsType (*MediaEngineSupportsProtocol)(const String& url);
- +typedef void (*MediaEngineRegistrar)(CreateMediaEnginePlayer, MediaEngineSupportedTypes, MediaEngineSupportsType, MediaEngineSupportsProtocol,
- + MediaEngineGetSitesInMediaCache, MediaEngineClearMediaCache, MediaEngineClearMediaCacheForSite);
- +#else
- +typedef void (*MediaEngineRegistrar)(CreateMediaEnginePlayer, MediaEngineSupportedTypes, MediaEngineSupportsType,
- + MediaEngineGetSitesInMediaCache, MediaEngineClearMediaCache, MediaEngineClearMediaCacheForSite);
- +#endif
- }
- diff --git a/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp b/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp
- index 839708e..d3ae420 100644
- --- a/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp
- +++ b/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp
- @@ -173,7 +173,11 @@ PassOwnPtr<MediaPlayerPrivateInterface> MediaPlayerPrivateGStreamer::create(Medi
- void MediaPlayerPrivateGStreamer::registerMediaEngine(MediaEngineRegistrar registrar)
- {
- if (isAvailable())
- +#if ENABLE(MEDIA_STREAM)
- + registrar(create, getSupportedTypes, supportsType, supportsProtocol, 0, 0, 0);
- +#else
- registrar(create, getSupportedTypes, supportsType, 0, 0, 0);
- +#endif
- }
- bool initializeGStreamerAndRegisterWebKitElements()
- @@ -1453,6 +1457,17 @@ void MediaPlayerPrivateGStreamer::loadingFailed(MediaPlayer::NetworkState error)
- }
- }
- +#if ENABLE(MEDIA_STREAM)
- +MediaPlayer::SupportsType MediaPlayerPrivateGStreamer::supportsProtocol(const String& url)
- +{
- + return MediaPlayer::IsNotSupported;
- +}
- +#endif
- +
- +
- void MediaPlayerPrivateGStreamer::setSize(const IntSize& size)
- {
- m_size = size;
- diff --git a/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.h b/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.h
- index 39ee9ce..63230c2 100644
- --- a/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.h
- +++ b/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.h
- @@ -131,6 +131,9 @@ class MediaPlayerPrivateGStreamer : public MediaPlayerPrivateInterface {
- static void getSupportedTypes(HashSet<String>&);
- static MediaPlayer::SupportsType supportsType(const String& type, const String& codecs);
- +#if ENABLE(MEDIA_STREAM)
- + static MediaPlayer::SupportsType supportsProtocol(const String& url);
- +#endif
- static bool isAvailable();
- void updateAudioSink();
- diff --git a/Source/WebCore/platform/graphics/gstreamer/StreamMediaPlayerPrivateGStreamer.cpp b/Source/WebCore/platform/graphics/gstreamer/StreamMediaPlayerPrivateGStreamer.cpp
- new file mode 100644
- index 0000000..dc550b1
- --- /dev/null
- +++ b/Source/WebCore/platform/graphics/gstreamer/StreamMediaPlayerPrivateGStreamer.cpp
- @@ -0,0 +1,622 @@
- +/*
- + * Copyright (C) 2012 Collabora Ltd. All rights reserved.
- + *
- + * This library is free software; you can redistribute it and/or
- + * modify it under the terms of the GNU Lesser General Public
- + * License as published by the Free Software Foundation; either
- + * version 2 of the License, or (at your option) any later version.
- + *
- + * This library is distributed in the hope that it will be useful,
- + * but WITHOUT ANY WARRANTY; without even the implied warranty of
- + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- + * Lesser General Public License for more details.
- + *
- + * You should have received a copy of the GNU Lesser General Public
- + * License along with this library; if not, write to the Free Software
- + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- + */
- +
- +
- +#include "config.h"
- +
- +#if ENABLE(MEDIA_STREAM) && USE(GSTREAMER)
- +
- +#include "StreamMediaPlayerPrivateGStreamer.h"
- +
- +#include "CentralPipelineUnit.h"
- +#include "MediaStream.h"
- +
- +#include "GraphicsContext.h"
- +#include "GraphicsTypes.h"
- +#include "GStreamerGWorld.h"
- +#include "ImageGStreamer.h"
- +#include "IntRect.h"
- +#include "KURL.h"
- +#include "MediaPlayer.h"
- +#include "MediaStreamRegistry.h"
- +#include "VideoSinkGStreamer.h"
- +#include "WebKitWebSourceGStreamer.h"
- +#include <wtf/gobject/GOwnPtr.h>
- +#include <gst/gst.h>
- +#include <gst/video/video.h>
- +#include <math.h>
- +
- +#include "Logging.h"
- +
- +namespace WebCore {
- +
- +void streamMediaPlayerPrivateVolumeChangedCallback(GObject* element, GParamSpec* pspec, gpointer data);
- +void streamMediaPlayerPrivateMuteChangedCallback(GObject* element, GParamSpec* pspec, gpointer data);
- +gboolean streamMediaPlayerPrivateVolumeChangeTimeoutCallback(StreamMediaPlayerPrivateGStreamer*);
- +gboolean streamMediaPlayerPrivateMuteChangeTimeoutCallback(StreamMediaPlayerPrivateGStreamer*);
- +
- +
- +static bool doGstInit();
- +
- +static int greatestCommonDivisor(int a, int b)
- +{
- + while (b) {
- + int temp = a;
- + a = b;
- + b = temp % b;
- + }
- +
- + return ABS(a);
- +}
- +
- +void streamMediaPlayerPrivateVolumeChangedCallback(GObject *element, GParamSpec *pspec, gpointer data)
- +{
- + StreamMediaPlayerPrivateGStreamer* mp = reinterpret_cast<StreamMediaPlayerPrivateGStreamer*>(data);
- + mp->volumeChanged();
- +}
- +
- +gboolean streamMediaPlayerPrivateVolumeChangeTimeoutCallback(StreamMediaPlayerPrivateGStreamer* player)
- +{
- + player->notifyPlayerOfVolumeChange();
- + return FALSE;
- +}
- +
- +void streamMediaPlayerPrivateMuteChangedCallback(GObject *element, GParamSpec *pspec, gpointer data)
- +{
- + StreamMediaPlayerPrivateGStreamer* mp = reinterpret_cast<StreamMediaPlayerPrivateGStreamer*>(data);
- + mp->muteChanged();
- +}
- +
- +gboolean streamMediaPlayerPrivateMuteChangeTimeoutCallback(StreamMediaPlayerPrivateGStreamer* player)
- +{
- + player->notifyPlayerOfMute();
- + return FALSE;
- +}
- +
- +
- +StreamMediaPlayerPrivateGStreamer::StreamMediaPlayerPrivateGStreamer(MediaPlayer* player)
- + : m_player(player)
- + , m_webkitVideoSink(0)
- + , m_videoSinkBin(0)
- + , m_audioSinkBin(0)
- + , m_volume(0)
- + , m_buffer(0)
- + , m_networkState(MediaPlayer::Empty)
- + , m_readyState(MediaPlayer::HaveNothing)
- + , m_paused(true)
- + , m_stopped(true)
- + , m_volumeTimerHandler(0)
- + , m_muteTimerHandler(0)
- + , m_repaintCallbackHandlerId(0)
- +{
- + //LOG(StreamAPI, "StreamAPI - Creating Stream media player");
- +
- + if (doGstInit()) {
- + createGSTVideoSinkBin();
- + createGSTAudioSinkBin();
- + }
- +}
- +
- +StreamMediaPlayerPrivateGStreamer::~StreamMediaPlayerPrivateGStreamer()
- +{
- + LOG(MediaStream, "StreamMediaPlayerPrivateGStreamer destructor called.");
- +
- + g_signal_handler_disconnect(m_webkitVideoSink, m_repaintCallbackHandlerId);
- +
- + if (m_buffer)
- + gst_buffer_unref(m_buffer);
- + m_buffer = 0;
- +
- + stop();
- +
- + if (m_audioSinkBin) {
- + gst_object_unref(m_audioSinkBin);
- + m_audioSinkBin = 0;
- + }
- +
- + if (m_videoSinkBin) {
- + gst_object_unref(m_videoSinkBin);
- + m_videoSinkBin = 0;
- + }
- +
- + m_player = 0;
- +
- + if (m_muteTimerHandler)
- + g_source_remove(m_muteTimerHandler);
- +
- + if (m_volumeTimerHandler)
- + g_source_remove(m_volumeTimerHandler);
- +}
- +
- +void StreamMediaPlayerPrivateGStreamer::play()
- +{
- + LOG(MediaStream, "StreamMediaPlayerPrivateGStreamer::play() called.");
- + m_paused = false;
- +
- + internalLoad();
- +}
- +
- +void StreamMediaPlayerPrivateGStreamer::pause()
- +{
- + LOG(MediaStream, "StreamMediaPlayerPrivateGStreamer::pause() called.");
- + m_paused = true;
- + stop();
- +}
- +
- +
- +bool StreamMediaPlayerPrivateGStreamer::hasVideo() const
- +{
- + return !m_videoSourceId.isEmpty();
- +}
- +
- +bool StreamMediaPlayerPrivateGStreamer::hasAudio() const
- +{
- + return !m_audioSourceId.isEmpty();
- +}
- +
- +void StreamMediaPlayerPrivateGStreamer::setVolume(float volume)
- +{
- + if (!m_volume)
- + return;
- + g_object_set(m_volume, "volume", static_cast<double>(volume), NULL);
- +}
- +
- +void StreamMediaPlayerPrivateGStreamer::notifyPlayerOfVolumeChange()
- +{
- + m_volumeTimerHandler = 0;
- +
- + if (!m_player || !m_volume)
- + return;
- + double volume;
- + g_object_get(m_volume, "volume", &volume, NULL);
- + m_player->volumeChanged(static_cast<float>(volume));
- +}
- +
- +void StreamMediaPlayerPrivateGStreamer::volumeChanged()
- +{
- + if (m_volumeTimerHandler)
- + g_source_remove(m_volumeTimerHandler);
- + m_volumeTimerHandler = g_timeout_add(0, reinterpret_cast<GSourceFunc>(streamMediaPlayerPrivateVolumeChangeTimeoutCallback), this);
- +}
- +
- +
- +bool StreamMediaPlayerPrivateGStreamer::supportsMuting() const
- +{
- + return true;
- +}
- +
- +void StreamMediaPlayerPrivateGStreamer::setMuted(bool muted)
- +{
- + if (!m_volume)
- + return;
- +
- + g_object_set(m_volume, "mute", muted, NULL);
- +}
- +
- +void StreamMediaPlayerPrivateGStreamer::notifyPlayerOfMute()
- +{
- + m_muteTimerHandler = 0;
- +
- + if (!m_player || !m_volume)
- + return;
- +
- + gboolean muted;
- + g_object_get(m_volume, "mute", &muted, NULL);
- + m_player->muteChanged(static_cast<bool>(muted));
- +}
- +
- +void StreamMediaPlayerPrivateGStreamer::muteChanged()
- +{
- + if (m_muteTimerHandler)
- + g_source_remove(m_muteTimerHandler);
- + m_muteTimerHandler = g_timeout_add(0, reinterpret_cast<GSourceFunc>(streamMediaPlayerPrivateMuteChangeTimeoutCallback), this);
- +}
- +
- +
- +void StreamMediaPlayerPrivateGStreamer::load(const String &url)
- +{
- + //LOG(StreamAPI, "StreamAPI - Stream media player - load");
- +
- + m_streamDescriptor = MediaStreamRegistry::registry().lookupMediaStreamDescriptor(url);
- + if (!m_streamDescriptor || m_streamDescriptor->ended()) {
- + loadingFailed(MediaPlayer::NetworkError);
- + return;
- + }
- +
- + m_readyState = MediaPlayer::HaveNothing;
- + m_networkState = MediaPlayer::Empty;
- + m_player->networkStateChanged();
- + m_player->readyStateChanged();
- +
- + if (!internalLoad())
- + return;
- +
- + if (hasVideo()) {
- + // Wait for first video frame to set HaveEnoughData
- + m_readyState = MediaPlayer::HaveNothing;
- + } else {
- + m_readyState = MediaPlayer::HaveEnoughData;
- + }
- +
- + m_networkState = MediaPlayer::Loaded;
- + m_player->networkStateChanged();
- + m_player->readyStateChanged();
- +
- +}
- +
- +void StreamMediaPlayerPrivateGStreamer::loadingFailed(MediaPlayer::NetworkState error)
- +{
- +
- + if (m_networkState != error) {
- + m_networkState = error;
- + m_player->networkStateChanged();
- + }
- + if (m_readyState != MediaPlayer::HaveNothing) {
- + m_readyState = MediaPlayer::HaveNothing;
- + m_player->readyStateChanged();
- + }
- +}
- +
- +bool StreamMediaPlayerPrivateGStreamer::didLoadingProgress() const
- +{
- + return true;
- +}
- +
- +bool StreamMediaPlayerPrivateGStreamer::internalLoad()
- +{
- + if (m_stopped) {
- + m_stopped = false;
- + if (!m_streamDescriptor || m_streamDescriptor->ended()) {
- + loadingFailed(MediaPlayer::NetworkError);
- + return false;
- + }
- + return connectToGSTLiveStream(m_streamDescriptor.get());
- + }
- + return false;
- +}
- +
- +void StreamMediaPlayerPrivateGStreamer::stop()
- +{
- + if (!m_stopped) {
- + m_stopped = true;
- + CentralPipelineUnit &cpu = centralPipelineUnit();
- + if (!m_audioSourceId.isEmpty()) {
- + LOG(MediaStream, "StreamMediaPlayerPrivateGStreamer stop: disconnecting audio");
- + cpu.disconnectFromSource(m_audioSourceId, m_audioSinkBin);
- + }
- + if (!m_videoSourceId.isEmpty()) {
- + LOG(MediaStream, "StreamMediaPlayerPrivateGStreamer stop: disconnecting video");
- + cpu.disconnectFromSource(m_videoSourceId, m_videoSinkBin);
- + }
- + m_audioSourceId = "";
- + m_videoSourceId = "";
- + }
- +}
- +
- +
- +void mediaPlayerPrivateRepaintCallback(WebKitVideoSink*, GstBuffer *buffer, StreamMediaPlayerPrivateGStreamer* playerPrivate)
- +{
- + g_return_if_fail(GST_IS_BUFFER(buffer));
- +
- + if (!playerPrivate->m_buffer) {
- + playerPrivate->m_readyState = MediaPlayer::HaveEnoughData;
- + playerPrivate->m_player->readyStateChanged();
- + }
- +
- + if (!playerPrivate->m_paused || !playerPrivate->m_buffer) {
- + gst_buffer_replace(&playerPrivate->m_buffer, buffer);
- +
- + IntSize size = playerPrivate->calculateSize();
- + playerPrivate->updateCurrentSize(size);
- +
- + playerPrivate->repaint();
- + }
- +}
- +
- +
- +PassOwnPtr<MediaPlayerPrivateInterface> StreamMediaPlayerPrivateGStreamer::create(MediaPlayer* player)
- +{
- + return adoptPtr(new StreamMediaPlayerPrivateGStreamer(player));
- +}
- +
- +void StreamMediaPlayerPrivateGStreamer::registerMediaEngine(MediaEngineRegistrar registrar)
- +{
- + if (isAvailable())
- + registrar(create, getSupportedTypes, supportsType, supportsProtocol, 0, 0, 0);
- +}
- +
- +void StreamMediaPlayerPrivateGStreamer::getSupportedTypes(HashSet<String>& types)
- +{
- + types.add(String("video/x-raw-yuv"));
- + types.add(String("audio/x-raw-int"));
- +}
- +
- +MediaPlayer::SupportsType StreamMediaPlayerPrivateGStreamer::supportsType(const String& type, const String& codecs)
- +{
- + return MediaPlayer::IsNotSupported;
- +}
- +
- +MediaPlayer::SupportsType StreamMediaPlayerPrivateGStreamer::supportsProtocol(const String& url)
- +{
- + if (url.isNull() || url.isEmpty())
- + return MediaPlayer::IsNotSupported;
- +
- + return MediaStreamRegistry::registry().lookupMediaStreamDescriptor(url) ? MediaPlayer::IsSupported : MediaPlayer::IsNotSupported;
- +}
- +
- +
- +static bool gstInitialized = false;
- +
- +static bool doGstInit()
- +{
- + if (!gstInitialized) {
- + GOwnPtr<GError> error;
- + gstInitialized = gst_init_check(0, 0, &error.outPtr());
- + }
- + return gstInitialized;
- +}
- +
- +
- +bool StreamMediaPlayerPrivateGStreamer::isAvailable()
- +{
- +
- + if (!doGstInit())
- + return false;
- +
- + return true;
- +}
- +
- +
- +void StreamMediaPlayerPrivateGStreamer::repaint()
- +{
- + m_player->repaint();
- +}
- +
- +void StreamMediaPlayerPrivateGStreamer::paint(GraphicsContext* context, const IntRect& rect)
- +{
- + if (context->paintingDisabled())
- + return;
- +
- + if (!m_player->visible())
- + return;
- + if (!m_buffer)
- + return;
- +
- + RefPtr<ImageGStreamer> gstImage = ImageGStreamer::createImage(m_buffer);
- + if (!gstImage)
- + return;
- +
- + context->drawImage(reinterpret_cast<Image*>(gstImage->image().get()), ColorSpaceSRGB,
- + rect, CompositeCopy, WebCore::DoNotRespectImageOrientation, false);
- +}
- +
- +
- +// Returns the size of the video
- +IntSize StreamMediaPlayerPrivateGStreamer::naturalSize() const
- +{
- + return m_currentSize;
- +}
- +
- +bool StreamMediaPlayerPrivateGStreamer::supportsFullscreen() const
- +{
- + return false;
- +}
- +
- +PlatformMedia StreamMediaPlayerPrivateGStreamer::platformMedia() const
- +{
- + PlatformMedia p;
- + p.type = PlatformMedia::GStreamerGWorldType;
- + p.media.gstreamerGWorld = m_gstGWorld.get();
- + return p;
- +}
- +
- +
- +void StreamMediaPlayerPrivateGStreamer::createGSTVideoSinkBin()
- +{
- + LOG(MediaStream, "createGSTVideoSinkBin called");
- + m_gstGWorld = GStreamerGWorld::createGWorld(0);
- + m_webkitVideoSink = webkitVideoSinkNew(m_gstGWorld.get());
- +
- + gchar* name = gst_element_get_name(m_webkitVideoSink);
- + LOG(MediaStream, "m_webkitVideoSink=%p name=%s", m_webkitVideoSink, name);
- +
- + m_repaintCallbackHandlerId = g_signal_connect(m_webkitVideoSink, "repaint-requested", G_CALLBACK(mediaPlayerPrivateRepaintCallback), this);
- +
- + m_videoSinkBin = gst_bin_new(0);
- + GstElement* colorspace = gst_element_factory_make("ffmpegcolorspace", 0);
- + GstElement* videoTee = gst_element_factory_make("tee", "videoTee");
- + GstElement* queue = gst_element_factory_make("queue", 0);
- + GstElement* identity = gst_element_factory_make("identity", "videoValve");
- +
- + // Take ownership.
- + gst_object_ref_sink(m_videoSinkBin);
- +
- + // Build a new video sink consisting of a bin containing a tee
- + // (meant to distribute data to multiple video sinks) and our
- + // internal video sink. For fullscreen we create an autovideosink
- + // and initially block the data flow towards it and configure it
- +
- + gst_bin_add_many(GST_BIN(m_videoSinkBin), colorspace, videoTee, queue, identity, m_webkitVideoSink, NULL);
- +
- + gst_element_link(colorspace, videoTee);
- + // Link a new src pad from tee to queue1.
- + GstPad* srcPad = gst_element_get_request_pad(videoTee, "src%d");
- + GstPad* sinkPad = gst_element_get_static_pad(queue, "sink");
- + gst_pad_link(srcPad, sinkPad);
- + gst_object_unref(GST_OBJECT(srcPad));
- + gst_object_unref(GST_OBJECT(sinkPad));
- + gst_element_link_many(queue, identity, m_webkitVideoSink, NULL);
- +
- + g_object_set(m_webkitVideoSink, "async", FALSE, NULL);
- +
- + // Add a ghostpad to the bin so it can proxy to tee.
- + GstPad* pad = gst_element_get_static_pad(colorspace, "sink");
- + gst_element_add_pad(m_videoSinkBin, gst_ghost_pad_new("sink", pad));
- + gst_object_unref(GST_OBJECT(pad));
- +
- +}
- +
- +void StreamMediaPlayerPrivateGStreamer::createGSTAudioSinkBin()
- +{
- +
- + m_audioSinkBin = gst_bin_new(0);
- + gst_object_ref_sink(m_audioSinkBin);
- +
- + m_volume = gst_element_factory_make("volume", "volume");
- +
- + g_object_set(m_volume, "mute", m_player->muted(), "volume", m_player->volume(), NULL);
- +
- + g_signal_connect(m_volume, "notify::volume", G_CALLBACK(streamMediaPlayerPrivateVolumeChangedCallback), this);
- + g_signal_connect(m_volume, "notify::mute", G_CALLBACK(streamMediaPlayerPrivateMuteChangedCallback), this);
- +
- +
- + GstElement *audioSink = gst_element_factory_make("autoaudiosink", 0);
- + gst_bin_add_many(GST_BIN(m_audioSinkBin), m_volume, audioSink, NULL);
- + gst_element_link_many(m_volume, audioSink, NULL);
- +
- + GstPad* pad = gst_element_get_static_pad(m_volume, "sink");
- + gst_element_add_pad(m_audioSinkBin, gst_ghost_pad_new("sink", pad));
- + gst_object_unref(GST_OBJECT(pad));
- +}
- +
- +bool StreamMediaPlayerPrivateGStreamer::connectToGSTLiveStream(MediaStreamDescriptor* streamDescriptor)
- +{
- + LOG(MediaStream, "connectToGSTLiveStream called");
- + if (!streamDescriptor)
- + return false;
- +
- + // FIXME: Error handling.. this could fail.. and this method never returns false.
- +
- + CentralPipelineUnit &cpu = centralPipelineUnit();
- +
- + if (!m_audioSourceId.isEmpty()) {
- + cpu.disconnectFromSource(m_audioSourceId, m_audioSinkBin);
- + m_audioSourceId = "";
- + }
- +
- + if (!m_videoSourceId.isEmpty()) {
- + cpu.disconnectFromSource(m_videoSourceId, m_videoSinkBin);
- + m_videoSourceId = "";
- + }
- +
- + for (unsigned i = 0; i < streamDescriptor->numberOfAudioComponents(); i++) {
- + MediaStreamComponent* component = streamDescriptor->audioComponent(i);
- + if (!component->enabled())
- + continue;
- +
- + MediaStreamSource* source = component->source();
- + if (source->type() == MediaStreamSource::TypeAudio) {
- + if (cpu.connectToSource(source->id(), m_audioSinkBin)) {
- + m_audioSourceId = source->id();
- + // FIXME: Break since we don't support mixing of audio tracks yet.
- + break;
- + }
- + }
- + }
- +
- + for (unsigned i = 0; i < streamDescriptor->numberOfVideoComponents(); i++) {
- + MediaStreamComponent* component = streamDescriptor->videoComponent(i);
- + if (!component->enabled())
- + continue;
- +
- + MediaStreamSource* source = component->source();
- + if (source->type() == MediaStreamSource::TypeVideo) {
- + if (cpu.connectToSource(source->id(), m_videoSinkBin)) {
- + m_audioSourceId = source->id();
- + // FIXME: Break since we don't support mixing of audio tracks yet.
- + break;
- + }
- + }
- + }
- +
- + return true;
- +}
- +
- +IntSize StreamMediaPlayerPrivateGStreamer::calculateSize()
- +{
- +
- + if (!hasVideo())
- + return IntSize();
- +
- + GstPad* pad = gst_element_get_static_pad(m_webkitVideoSink, "sink");
- + if (!pad)
- + return IntSize();
- +
- + guint64 width = 0, height = 0;
- + GstCaps* caps = GST_PAD_CAPS(pad);
- + int pixelAspectRatioNumerator, pixelAspectRatioDenominator;
- + int displayWidth, displayHeight, displayAspectRatioGCD;
- + int originalWidth = 0, originalHeight = 0;
- +
- + // TODO: handle possible clean aperture data. See
- + // https://bugzilla.gnome.org/show_bug.cgi?id=596571
- + // TODO: handle possible transformation matrix. See
- + // https://bugzilla.gnome.org/show_bug.cgi?id=596326
- +
- + // Get the video PAR and original size.
- + if (!GST_IS_CAPS(caps) || !gst_caps_is_fixed(caps)
- + || !gst_video_format_parse_caps(caps, 0, &originalWidth, &originalHeight)
- + || !gst_video_parse_caps_pixel_aspect_ratio(caps, &pixelAspectRatioNumerator,
- + &pixelAspectRatioDenominator)) {
- + gst_object_unref(GST_OBJECT(pad));
- + return IntSize();
- + }
- +
- + gst_object_unref(GST_OBJECT(pad));
- +
- + //LOG_VERBOSE(Media, "Original video size: %dx%d", originalWidth, originalHeight);
- + //LOG_VERBOSE(Media, "Pixel aspect ratio: %d/%d", pixelAspectRatioNumerator, pixelAspectRatioDenominator);
- +
- + // Calculate DAR based on PAR and video size.
- + displayWidth = originalWidth * pixelAspectRatioNumerator;
- + displayHeight = originalHeight * pixelAspectRatioDenominator;
- +
- + // Divide display width and height by their GCD to avoid possible overflows.
- + displayAspectRatioGCD = greatestCommonDivisor(displayWidth, displayHeight);
- + displayWidth /= displayAspectRatioGCD;
- + displayHeight /= displayAspectRatioGCD;
- +
- + // Apply DAR to original video size. This is the same behavior as in xvimagesink's setcaps function.
- + if (!(originalHeight % displayHeight)) {
- + //LOG_VERBOSE(Media, "Keeping video original height");
- + width = gst_util_uint64_scale_int(originalHeight, displayWidth, displayHeight);
- + height = static_cast<guint64>(originalHeight);
- + } else if (!(originalWidth % displayWidth)) {
- + // LOG_VERBOSE(Media, "Keeping video original width");
- + height = gst_util_uint64_scale_int(originalWidth, displayHeight, displayWidth);
- + width = static_cast<guint64>(originalWidth);
- + } else {
- + // LOG_VERBOSE(Media, "Approximating while keeping original video height");
- + width = gst_util_uint64_scale_int(originalHeight, displayWidth, displayHeight);
- + height = static_cast<guint64>(originalHeight);
- + }
- +
- + // LOG_VERBOSE(Media, "Natural size: %" G_GUINT64_FORMAT "x%" G_GUINT64_FORMAT, width, height);
- + return IntSize(static_cast<int>(width), static_cast<int>(height));
- +}
- +
- +void StreamMediaPlayerPrivateGStreamer::updateCurrentSize(IntSize& size)
- +{
- + m_currentSize.setWidth(size.width());
- + m_currentSize.setHeight(size.height());
- + m_player->sizeChanged();
- +}
- +
- +} // namespace WebCore
- +
- +#endif // ENABLE(MEDIA_STREAM) && USE(GSTREAMER)
- diff --git a/Source/WebCore/platform/graphics/gstreamer/StreamMediaPlayerPrivateGStreamer.h b/Source/WebCore/platform/graphics/gstreamer/StreamMediaPlayerPrivateGStreamer.h
- new file mode 100644
- index 0000000..6c35346
- --- /dev/null
- +++ b/Source/WebCore/platform/graphics/gstreamer/StreamMediaPlayerPrivateGStreamer.h
- @@ -0,0 +1,153 @@
- +/*
- + * Copyright (C) 2012 Collabora Ltd. All rights reserved.
- + *
- + * This library is free software; you can redistribute it and/or
- + * modify it under the terms of the GNU Lesser General Public
- + * License as published by the Free Software Foundation; either
- + * version 2 of the License, or (at your option) any later version.
- + *
- + * This library is distributed in the hope that it will be useful,
- + * but WITHOUT ANY WARRANTY; without even the implied warranty of
- + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- + * Lesser General Public License for more details.
- + *
- + * You should have received a copy of the GNU Lesser General Public
- + * License along with this library; if not, write to the Free Software
- + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- + */
- +
- +#ifndef StreamMediaPlayerPrivateGStreamer_h
- +#define StreamMediaPlayerPrivateGStreamer_h
- +
- +#if ENABLE(MEDIA_STREAM) && USE(GSTREAMER)
- +
- +#include "MediaPlayerPrivate.h"
- +#include "Timer.h"
- +#include "TimeRanges.h"
- +
- +#include <glib.h>
- +#include <gst/gst.h>
- +#include <wtf/Forward.h>
- +#include <wtf/Vector.h>
- +
- +typedef struct _WebKitVideoSink WebKitVideoSink;
- +
- +namespace WebCore {
- +
- +class StreamComponent;
- +class MediaStreamDescriptor;
- +class GStreamerGWorld;
- +
- +class StreamMediaPlayerPrivateGStreamer : public MediaPlayerPrivateInterface {
- + friend void mediaPlayerPrivateRepaintCallback(WebKitVideoSink*, GstBuffer* buffer, StreamMediaPlayerPrivateGStreamer* playerPrivate);
- +public:
- + ~StreamMediaPlayerPrivateGStreamer();
- + static void registerMediaEngine(MediaEngineRegistrar);
- +
- +
- + virtual void load(const String&);
- + virtual void cancelLoad() { }
- +
- + virtual void prepareToPlay() { }
- + void play();
- + void pause();
- +
- + IntSize naturalSize() const;
- +
- + bool hasVideo() const;
- + bool hasAudio() const;
- +
- + 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 setRate(float) { }
- + virtual void setPreservesPitch(bool) { }
- + virtual bool paused() const { return m_paused; }
- +
- + void setVolume(float);
- + void volumeChanged();
- + void notifyPlayerOfVolumeChange();
- +
- + bool supportsMuting() const;
- + void setMuted(bool);
- + void muteChanged();
- + void notifyPlayerOfMute();
- +
- +
- + virtual bool hasClosedCaptions() const { return false; }
- + virtual void setClosedCaptionsVisible(bool) { };
- +
- + virtual MediaPlayer::NetworkState networkState() const { return m_networkState; }
- + virtual MediaPlayer::ReadyState readyState() const { return m_readyState; }
- +
- + virtual float maxTimeSeekable() const { return 0; }
- + virtual PassRefPtr<TimeRanges> buffered() const { return TimeRanges::create(); }
- + bool didLoadingProgress() const;
- +
- + virtual unsigned totalBytes() const { return 0; }
- + virtual unsigned bytesLoaded() const { return 0; }
- +
- + virtual void setSize(const IntSize&) { }
- +
- + void repaint();
- + virtual void paint(GraphicsContext*, const IntRect&);
- +
- + virtual bool canLoadPoster() const { return false; }
- + virtual void setPoster(const String&) { }
- +
- + virtual bool hasSingleSecurityOrigin() const { return true; }
- +
- + bool supportsFullscreen() const;
- + PlatformMedia platformMedia() const;
- +
- +private:
- + StreamMediaPlayerPrivateGStreamer(MediaPlayer*);
- +
- + static PassOwnPtr<MediaPlayerPrivateInterface> create(MediaPlayer* player);
- +
- + static void getSupportedTypes(HashSet<String>&);
- + static MediaPlayer::SupportsType supportsType(const String& type, const String& codecs);
- + static MediaPlayer::SupportsType supportsProtocol(const String& url);
- + static bool isAvailable();
- + void createGSTAudioSinkBin();
- + void createGSTVideoSinkBin();
- + bool connectToGSTLiveStream(MediaStreamDescriptor*);
- + void loadingFailed(MediaPlayer::NetworkState error);
- + bool internalLoad();
- + void stop();
- + IntSize calculateSize();
- + void updateCurrentSize(IntSize&);
- +
- +private:
- + MediaPlayer* m_player;
- + GstElement* m_webkitVideoSink;
- + GstElement* m_videoSinkBin;
- + GstElement* m_audioSinkBin;
- + GstElement* m_volume;
- + GstBuffer* m_buffer;
- + MediaPlayer::NetworkState m_networkState;
- + MediaPlayer::ReadyState m_readyState;
- + bool m_paused;
- + bool m_stopped;
- + RefPtr<GStreamerGWorld> m_gstGWorld;
- + guint m_volumeTimerHandler;
- + guint m_muteTimerHandler;
- + String m_videoSourceId;
- + String m_audioSourceId;
- + RefPtr<MediaStreamDescriptor> m_streamDescriptor;
- + IntSize m_currentSize;
- + gulong m_repaintCallbackHandlerId;
- +};
- +
- +
- +
- +} // namespace WebCore
- +
- +#endif // ENABLE(MEDIA_STREAM) && USE(GSTREAMER)
- +
- +#endif // StreamMediaPlayerPrivateGStreamer_h
- --
- 1.7.10
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement