Changeset 177790 in webkit
- Timestamp:
- Dec 29, 2014 6:46:39 AM (9 years ago)
- Location:
- trunk
- Files:
-
- 11 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r177785 r177790 1 2014-12-29 Sebastian Dröge <sebastian@centricular.com> 2 3 Enable MediaSource tests for the GTK port 4 https://bugs.webkit.org/show_bug.cgi?id=139441 5 6 Reviewed by Philippe Normand. 7 8 * platform/gtk/TestExpectations: 9 Enable MediaSource tests that are actually succeeding for 10 the GTK port. 11 1 12 2014-12-28 Alexey Proskuryakov <ap@apple.com> 2 13 -
trunk/LayoutTests/platform/gtk/TestExpectations
r177583 r177790 226 226 227 227 # Tests for MediaSource API. Feature is not totally functional. 228 webkit.org/b/99065 http/tests/media/media-source [ Skip ] 229 webkit.org/b/99065 media/media-source [ Skip ] 228 webkit.org/b/99065 http/tests/media/media-source/mediasource-append-buffer.html [ Skip ] 229 webkit.org/b/99065 http/tests/media/media-source/mediasource-append-stream.html [ Skip ] 230 webkit.org/b/99065 http/tests/media/media-source/mediasource-appendwindow.html [ Skip ] 231 webkit.org/b/99065 http/tests/media/media-source/mediasource-buffered.html [ Skip ] 232 webkit.org/b/99065 http/tests/media/media-source/mediasource-config-change-mp4-a-bitrate.html [ Skip ] 233 webkit.org/b/99065 http/tests/media/media-source/mediasource-config-change-mp4-av-audio-bitrate.html [ Skip ] 234 webkit.org/b/99065 http/tests/media/media-source/mediasource-config-change-mp4-av-framesize.html [ Skip ] 235 webkit.org/b/99065 http/tests/media/media-source/mediasource-config-change-mp4-av-video-bitrate.html [ Skip ] 236 webkit.org/b/99065 http/tests/media/media-source/mediasource-config-change-mp4-v-bitrate.html [ Skip ] 237 webkit.org/b/99065 http/tests/media/media-source/mediasource-config-change-mp4-v-framerate.html [ Skip ] 238 webkit.org/b/99065 http/tests/media/media-source/mediasource-config-change-mp4-v-framesize.html [ Skip ] 239 webkit.org/b/99065 http/tests/media/media-source/mediasource-config-change-webm-a-bitrate.html [ Skip ] 240 webkit.org/b/99065 http/tests/media/media-source/mediasource-config-change-webm-av-audio-bitrate.html [ Skip ] 241 webkit.org/b/99065 http/tests/media/media-source/mediasource-config-change-webm-av-framesize.html [ Skip ] 242 webkit.org/b/99065 http/tests/media/media-source/mediasource-config-change-webm-av-video-bitrate.html [ Skip ] 243 webkit.org/b/99065 http/tests/media/media-source/mediasource-config-change-webm-v-bitrate.html [ Skip ] 244 webkit.org/b/99065 http/tests/media/media-source/mediasource-config-change-webm-v-framerate.html [ Skip ] 245 webkit.org/b/99065 http/tests/media/media-source/mediasource-config-change-webm-v-framesize.html [ Skip ] 246 webkit.org/b/99065 http/tests/media/media-source/mediasource-duration.html [ Skip ] 247 webkit.org/b/99065 http/tests/media/media-source/mediasource-getvideoplaybackquality.html [ Skip ] 248 webkit.org/b/99065 http/tests/media/media-source/mediasource-is-type-supported.html [ Skip ] 249 webkit.org/b/99065 http/tests/media/media-source/mediasource-play.html [ Skip ] 250 webkit.org/b/99065 http/tests/media/media-source/mediasource-play-then-seek-back.html [ Skip ] 251 webkit.org/b/99065 http/tests/media/media-source/mediasource-redundant-seek.html [ Skip ] 252 webkit.org/b/99065 http/tests/media/media-source/mediasource-remove.html [ Skip ] 253 webkit.org/b/99065 http/tests/media/media-source/mediasource-seek-beyond-duration.html [ Skip ] 254 webkit.org/b/99065 http/tests/media/media-source/mediasource-seek-during-pending-seek.html [ Skip ] 255 webkit.org/b/99065 http/tests/media/media-source/mediasource-sourcebuffer-mode.html [ Skip ] 256 257 webkit.org/b/99065 media/media-source/media-source-append-failed.html [ Skip ] 258 webkit.org/b/99065 media/media-source/media-source-multiple-initialization-segments.html [ Skip ] 259 webkit.org/b/99065 media/media-source/media-source-append-nonsync-sample-after-abort.html [ Skip ] 260 webkit.org/b/99065 media/media-source/media-source-duplicate-seeked.html [ Skip ] 261 webkit.org/b/99065 media/media-source/media-source-canplaythrough.html [ Skip ] 262 webkit.org/b/99065 media/media-source/media-source-duration-after-append.html [ Skip ] 263 webkit.org/b/99065 media/media-source/media-source-end-of-stream-buffered.html [ Skip ] 264 webkit.org/b/99065 media/media-source/media-source-end-of-stream.html [ Skip ] 265 webkit.org/b/99065 media/media-source/media-source-fudge-factor.html [ Skip ] 266 webkit.org/b/99065 media/media-source/media-source-monitor-source-buffers.html [ Skip ] 267 webkit.org/b/99065 media/media-source/media-source-overlapping-append.html [ Skip ] 268 webkit.org/b/99065 media/media-source/media-source-overlapping-decodetime.html [ Skip ] 269 webkit.org/b/99065 media/media-source/media-source-play.html [ Skip ] 270 webkit.org/b/99065 media/media-source/media-source-remove.html [ Skip ] 271 webkit.org/b/99065 media/media-source/media-source-seek-complete.html [ Skip ] 272 webkit.org/b/99065 media/media-source/media-source-track-enabled.html [ Skip ] 273 webkit.org/b/99065 media/media-source/media-source-tracks.html [ Skip ] 274 webkit.org/b/99065 media/media-source/media-source-video-playback-quality.html [ Skip ] 230 275 231 276 # Encrypted Media Extensions are not enabled. -
trunk/Source/WebCore/ChangeLog
r177788 r177790 1 2014-12-29 Sebastian Dröge <sebastian@centricular.com> 2 3 [GStreamer] Rewrite MediaSource implementation 4 https://bugs.webkit.org/show_bug.cgi?id=139441 5 6 Reviewed by Philippe Normand. 7 8 This now is a clean reimplementation around appsrc that works good 9 enough for YouTube (except for seeking), but it still does not 10 implement the complete API correctly. Further work is required on 11 top of this and the Bugzilla ticket linked above contains some 12 further work in the right direction. 13 14 * platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp: 15 (WebCore::MediaPlayerPrivateGStreamer::doSeek): 16 (WebCore::MediaPlayerPrivateGStreamer::didLoadingProgress): 17 (WebCore::MediaPlayerPrivateGStreamer::sourceChanged): 18 (WebCore::MediaPlayerPrivateGStreamer::canSaveMediaData): 19 * platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.h: 20 (WebCore::MediaPlayerPrivateGStreamer::totalVideoFrames): 21 (WebCore::MediaPlayerPrivateGStreamer::droppedVideoFrames): 22 (WebCore::MediaPlayerPrivateGStreamer::corruptedVideoFrames): 23 (WebCore::MediaPlayerPrivateGStreamer::totalFrameDelay): 24 (WebCore::MediaPlayerPrivateGStreamer::isMediaSource): 25 * platform/graphics/gstreamer/MediaSourceGStreamer.cpp: 26 (WebCore::MediaSourceGStreamer::MediaSourceGStreamer): 27 (WebCore::MediaSourceGStreamer::addSourceBuffer): 28 (WebCore::MediaSourceGStreamer::durationChanged): 29 (WebCore::MediaSourceGStreamer::markEndOfStream): 30 (WebCore::MediaSourceGStreamer::unmarkEndOfStream): 31 (WebCore::MediaSourceGStreamer::readyState): 32 (WebCore::MediaSourceGStreamer::setReadyState): 33 (WebCore::MediaSourceGStreamer::waitForSeekCompleted): 34 (WebCore::MediaSourceGStreamer::seekCompleted): 35 * platform/graphics/gstreamer/MediaSourceGStreamer.h: 36 * platform/graphics/gstreamer/SourceBufferPrivateGStreamer.cpp: 37 (WebCore::SourceBufferPrivateGStreamer::SourceBufferPrivateGStreamer): 38 (WebCore::SourceBufferPrivateGStreamer::~SourceBufferPrivateGStreamer): 39 (WebCore::SourceBufferPrivateGStreamer::setClient): 40 (WebCore::SourceBufferPrivateGStreamer::append): 41 (WebCore::SourceBufferPrivateGStreamer::removedFromMediaSource): 42 (WebCore::SourceBufferPrivateGStreamer::readyState): 43 (WebCore::SourceBufferPrivateGStreamer::setReadyState): 44 (WebCore::SourceBufferPrivateGStreamer::flushAndEnqueueNonDisplayingSamples): 45 (WebCore::SourceBufferPrivateGStreamer::enqueueSample): 46 (WebCore::SourceBufferPrivateGStreamer::isReadyForMoreSamples): 47 (WebCore::SourceBufferPrivateGStreamer::setActive): 48 (WebCore::SourceBufferPrivateGStreamer::stopAskingForMoreSamples): 49 (WebCore::SourceBufferPrivateGStreamer::notifyClientWhenReadyForMoreSamples): 50 * platform/graphics/gstreamer/SourceBufferPrivateGStreamer.h: 51 * platform/graphics/gstreamer/WebKitMediaSourceGStreamer.cpp: 52 (webkit_media_src_class_init): 53 (webkit_media_src_init): 54 (webKitMediaSrcFinalize): 55 (webKitMediaSrcSetProperty): 56 (webKitMediaSrcGetProperty): 57 (webKitMediaSrcDoAsyncStart): 58 (webKitMediaSrcDoAsyncDone): 59 (webKitMediaSrcChangeState): 60 (webKitMediaSrcQueryWithParent): 61 (webKitMediaSrcGetUri): 62 (webKitMediaSrcSetUri): 63 (WebCore::MediaSourceClientGStreamer::MediaSourceClientGStreamer): 64 (WebCore::MediaSourceClientGStreamer::~MediaSourceClientGStreamer): 65 (WebCore::MediaSourceClientGStreamer::addSourceBuffer): 66 (WebCore::MediaSourceClientGStreamer::durationChanged): 67 (WebCore::MediaSourceClientGStreamer::append): 68 (WebCore::MediaSourceClientGStreamer::markEndOfStream): 69 (WebCore::MediaSourceClientGStreamer::removedFromMediaSource): 70 (WTF::adoptGRef): 71 (WTF::refGPtr<WebKitMediaSrc>): 72 (WTF::derefGPtr<WebKitMediaSrc>): 73 (webKitMediaSrcAddSrc): Deleted. 74 (webKitMediaVideoSrcStop): Deleted. 75 (webKitMediaAudioSrcStop): Deleted. 76 (webKitMediaVideoSrcStart): Deleted. 77 (webKitMediaAudioSrcStart): Deleted. 78 (webKitMediaVideoSrcNeedDataMainCb): Deleted. 79 (webKitMediaAudioSrcNeedDataMainCb): Deleted. 80 (webKitMediaVideoSrcNeedDataCb): Deleted. 81 (webKitMediaAudioSrcNeedDataCb): Deleted. 82 (webKitMediaVideoSrcEnoughDataMainCb): Deleted. 83 (webKitMediaAudioSrcEnoughDataMainCb): Deleted. 84 (webKitMediaVideoSrcEnoughDataCb): Deleted. 85 (webKitMediaAudioSrcEnoughDataCb): Deleted. 86 (webKitMediaVideoSrcSeekMainCb): Deleted. 87 (webKitMediaAudioSrcSeekMainCb): Deleted. 88 (webKitMediaVideoSrcSeekDataCb): Deleted. 89 (webKitMediaAudioSrcSeekDataCb): Deleted. 90 (webKitMediaSrcSetMediaPlayer): Deleted. 91 (webKitMediaSrcSetPlayBin): Deleted. 92 (MediaSourceClientGstreamer::MediaSourceClientGstreamer): Deleted. 93 (MediaSourceClientGstreamer::~MediaSourceClientGstreamer): Deleted. 94 (MediaSourceClientGstreamer::didReceiveDuration): Deleted. 95 (MediaSourceClientGstreamer::didReceiveData): Deleted. 96 (MediaSourceClientGstreamer::didFinishLoading): Deleted. 97 (MediaSourceClientGstreamer::didFail): Deleted. 98 * platform/graphics/gstreamer/WebKitMediaSourceGStreamer.h: 99 Rewrite MediaSource implementation for GStreamer. The old code was 100 overly complicated and did not work at all for anything I've tested 101 it with. 102 1 103 2014-12-28 Gyuyoung Kim <gyuyoung.kim@samsung.com> 2 104 -
trunk/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp
r177058 r177790 565 565 gint64 startTime, endTime; 566 566 567 // TODO: Should do more than that, need to notify the media source 568 // and probably flush the pipeline at least. 569 if (isMediaSource()) 570 return true; 571 567 572 if (rate > 0) { 568 573 startTime = position; … … 1245 1250 bool MediaPlayerPrivateGStreamer::didLoadingProgress() const 1246 1251 { 1247 if (!m_playBin || !m_mediaDuration || !totalBytes())1252 if (!m_playBin || !m_mediaDuration || (!isMediaSource() && !totalBytes())) 1248 1253 return false; 1249 1254 float currentMaxTimeLoaded = maxTimeLoaded(); … … 1319 1324 if (m_mediaSource && WEBKIT_IS_MEDIA_SRC(m_source.get())) { 1320 1325 MediaSourceGStreamer::open(m_mediaSource.get(), WEBKIT_MEDIA_SRC(m_source.get())); 1321 webKitMediaSrcSetPlayBin(WEBKIT_MEDIA_SRC(m_source.get()), m_playBin.get());1322 1326 } 1323 1327 #endif … … 1997 2001 if (m_url.protocolIsInHTTPFamily()) 1998 2002 return true; 1999 2003 2000 2004 return false; 2001 2005 } -
trunk/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.h
r177058 r177790 175 175 virtual bool didPassCORSAccessCheck() const; 176 176 virtual bool canSaveMediaData() const override; 177 178 #if ENABLE(MEDIA_SOURCE) 179 // TODO: Implement 180 virtual unsigned long totalVideoFrames() { return 0; } 181 virtual unsigned long droppedVideoFrames() { return 0; } 182 virtual unsigned long corruptedVideoFrames() { return 0; } 183 virtual MediaTime totalFrameDelay() { return MediaTime::zeroTime(); } 184 #endif 177 185 178 186 private: … … 238 246 #if ENABLE(MEDIA_SOURCE) 239 247 RefPtr<MediaSourcePrivateClient> m_mediaSource; 248 bool isMediaSource() const { return m_mediaSource; } 249 #else 250 bool isMediaSource() const { return false; } 240 251 #endif 241 252 }; -
trunk/Source/WebCore/platform/graphics/gstreamer/MediaSourceGStreamer.cpp
r173318 r177790 2 2 * Copyright (C) 2013 Google Inc. All rights reserved. 3 3 * Copyright (C) 2013 Orange 4 * Copyright (C) 2014 Sebastian Dröge <sebastian@centricular.com> 4 5 * 5 6 * Redistribution and use in source and binary forms, with or without … … 35 36 #if ENABLE(MEDIA_SOURCE) && USE(GSTREAMER) 36 37 38 #include "NotImplemented.h" 37 39 #include "SourceBufferPrivateGStreamer.h" 38 40 #include "WebKitMediaSourceGStreamer.h" 41 39 42 #include <wtf/gobject/GRefPtr.h> 40 43 … … 48 51 49 52 MediaSourceGStreamer::MediaSourceGStreamer(MediaSourcePrivateClient* mediaSource, WebKitMediaSrc* src) 50 : m_client(adoptRef(new MediaSourceClientG streamer(src)))53 : m_client(adoptRef(new MediaSourceClientGStreamer(src))) 51 54 , m_mediaSource(mediaSource) 52 55 , m_readyState(MediaPlayer::HaveNothing) … … 61 64 MediaSourceGStreamer::AddStatus MediaSourceGStreamer::addSourceBuffer(const ContentType& contentType, RefPtr<SourceBufferPrivate>& sourceBufferPrivate) 62 65 { 63 sourceBufferPrivate = adoptRef(new SourceBufferPrivateGStreamer(m_client.get(), contentType)); 64 return MediaSourceGStreamer::Ok; 66 RefPtr<SourceBufferPrivateGStreamer> sourceBufferPrivateGStreamer = new SourceBufferPrivateGStreamer(m_client.get(), contentType); 67 68 sourceBufferPrivate = adoptRef(sourceBufferPrivateGStreamer.get()); 69 return m_client->addSourceBuffer(sourceBufferPrivateGStreamer, contentType); 65 70 } 66 71 67 72 void MediaSourceGStreamer::durationChanged() 68 73 { 69 m_client->d idReceiveDuration(m_mediaSource->duration().toDouble());74 m_client->durationChanged(m_mediaSource->duration()); 70 75 } 71 76 72 void MediaSourceGStreamer::markEndOfStream(EndOfStreamStatus )77 void MediaSourceGStreamer::markEndOfStream(EndOfStreamStatus status) 73 78 { 74 m_client-> didFinishLoading(0);79 m_client->markEndOfStream(status); 75 80 } 76 81 77 82 void MediaSourceGStreamer::unmarkEndOfStream() 78 83 { 84 notImplemented(); 85 } 86 87 MediaPlayer::ReadyState MediaSourceGStreamer::readyState() const 88 { 89 return m_readyState; 90 } 91 92 void MediaSourceGStreamer::setReadyState(MediaPlayer::ReadyState state) 93 { 94 m_readyState = state; 95 } 96 97 void MediaSourceGStreamer::waitForSeekCompleted() 98 { 99 notImplemented(); 100 } 101 102 void MediaSourceGStreamer::seekCompleted() 103 { 104 notImplemented(); 79 105 } 80 106 -
trunk/Source/WebCore/platform/graphics/gstreamer/MediaSourceGStreamer.h
r171033 r177790 2 2 * Copyright (C) 2013 Google Inc. All rights reserved. 3 3 * Copyright (C) 2013 Orange 4 * Copyright (C) 2014 Sebastian Dröge <sebastian@centricular.com> 4 5 * 5 6 * Redistribution and use in source and binary forms, with or without … … 39 40 namespace WebCore { 40 41 42 // FIXME: Should this be called MediaSourcePrivateGStreamer? 41 43 class MediaSourceGStreamer final : public MediaSourcePrivate { 42 44 public: 43 45 static void open(MediaSourcePrivateClient*, WebKitMediaSrc*); 44 ~MediaSourceGStreamer(); 46 virtual ~MediaSourceGStreamer(); 47 48 virtual AddStatus addSourceBuffer(const ContentType&, RefPtr<SourceBufferPrivate>&); 49 virtual void durationChanged(); 50 virtual void markEndOfStream(EndOfStreamStatus); 51 virtual void unmarkEndOfStream(); 52 53 virtual MediaPlayer::ReadyState readyState() const; 54 virtual void setReadyState(MediaPlayer::ReadyState); 55 56 virtual void waitForSeekCompleted(); 57 virtual void seekCompleted(); 45 58 46 59 private: 47 // MediaSourcePrivate 48 virtual AddStatus addSourceBuffer(const ContentType&, RefPtr<SourceBufferPrivate>&) override; 49 virtual void durationChanged() override; 50 virtual void markEndOfStream(EndOfStreamStatus) override; 51 virtual void unmarkEndOfStream() override; 52 virtual MediaPlayer::ReadyState readyState() const override { return m_readyState; } 53 virtual void setReadyState(MediaPlayer::ReadyState readyState) override { m_readyState = readyState; } 54 virtual void waitForSeekCompleted() override { } 55 virtual void seekCompleted() override { } 60 MediaSourceGStreamer(MediaSourcePrivateClient*, WebKitMediaSrc*); 56 61 57 RefPtr<MediaSourceClientG streamer> m_client;62 RefPtr<MediaSourceClientGStreamer> m_client; 58 63 MediaSourcePrivateClient* m_mediaSource; 59 MediaSourceGStreamer(MediaSourcePrivateClient*, WebKitMediaSrc*);60 64 MediaPlayer::ReadyState m_readyState; 61 65 }; -
trunk/Source/WebCore/platform/graphics/gstreamer/SourceBufferPrivateGStreamer.cpp
r168508 r177790 2 2 * Copyright (C) 2013 Google Inc. All rights reserved. 3 3 * Copyright (C) 2013 Orange 4 * Copyright (C) 2014 Sebastian Dröge <sebastian@centricular.com> 4 5 * 5 6 * Redistribution and use in source and binary forms, with or without … … 40 41 namespace WebCore { 41 42 42 SourceBufferPrivateGStreamer::SourceBufferPrivateGStreamer(PassRefPtr<MediaSourceClientGstreamer> client, const ContentType& contentType) 43 : m_readyState(MediaPlayer::HaveNothing) 43 SourceBufferPrivateGStreamer::SourceBufferPrivateGStreamer(PassRefPtr<MediaSourceClientGStreamer> client, const ContentType& contentType) 44 : m_type(contentType) 45 , m_client(client) 46 , m_readyState(MediaPlayer::HaveNothing) 44 47 { 45 m_client = client; 46 m_type = contentType.type(); 48 } 49 50 SourceBufferPrivateGStreamer::~SourceBufferPrivateGStreamer() 51 { 52 } 53 54 void SourceBufferPrivateGStreamer::setClient(SourceBufferPrivateClient* client) 55 { 56 m_sourceBufferPrivateClient = client; 47 57 } 48 58 … … 50 60 { 51 61 ASSERT(m_client); 52 m_client->didReceiveData(reinterpret_cast_ptr<const char*>(data), length, m_type);62 ASSERT(m_sourceBufferPrivateClient); 53 63 54 // FIXME: call SourceBufferPrivateClient::sourceBufferPrivateAppendComplete(). 64 SourceBufferPrivateClient::AppendResult result = m_client->append(this, data, length); 65 m_sourceBufferPrivateClient->sourceBufferPrivateAppendComplete(this, result); 55 66 } 56 67 … … 62 73 void SourceBufferPrivateGStreamer::removedFromMediaSource() 63 74 { 75 m_client->removedFromMediaSource(this); 76 } 77 78 MediaPlayer::ReadyState SourceBufferPrivateGStreamer::readyState() const 79 { 80 return m_readyState; 81 } 82 83 void SourceBufferPrivateGStreamer::setReadyState(MediaPlayer::ReadyState state) 84 { 85 m_readyState = state; 86 } 87 88 // TODO: Implement these 89 void SourceBufferPrivateGStreamer::flushAndEnqueueNonDisplayingSamples(Vector<RefPtr<MediaSample>>, AtomicString) 90 { 91 notImplemented(); 92 } 93 94 void SourceBufferPrivateGStreamer::enqueueSample(PassRefPtr<MediaSample>, AtomicString) 95 { 96 notImplemented(); 97 } 98 99 bool SourceBufferPrivateGStreamer::isReadyForMoreSamples(AtomicString) 100 { 101 notImplemented(); 102 103 return false; 104 } 105 106 void SourceBufferPrivateGStreamer::setActive(bool) 107 { 108 notImplemented(); 109 } 110 111 void SourceBufferPrivateGStreamer::stopAskingForMoreSamples(AtomicString) 112 { 113 notImplemented(); 114 } 115 116 void SourceBufferPrivateGStreamer::notifyClientWhenReadyForMoreSamples(AtomicString) 117 { 64 118 notImplemented(); 65 119 } -
trunk/Source/WebCore/platform/graphics/gstreamer/SourceBufferPrivateGStreamer.h
r168508 r177790 2 2 * Copyright (C) 2013 Google Inc. All rights reserved. 3 3 * Copyright (C) 2013 Orange 4 * Copyright (C) 2014 Sebastian Dröge <sebastian@centricular.com> 4 5 * 5 6 * Redistribution and use in source and binary forms, with or without … … 35 36 #if ENABLE(MEDIA_SOURCE) && USE(GSTREAMER) 36 37 38 #include "ContentType.h" 37 39 #include "SourceBufferPrivate.h" 38 40 #include "WebKitMediaSourceGStreamer.h" … … 42 44 class SourceBufferPrivateGStreamer final : public SourceBufferPrivate { 43 45 public: 44 SourceBufferPrivateGStreamer(PassRefPtr<MediaSourceClientG streamer>, const ContentType&);45 ~SourceBufferPrivateGStreamer() { }46 SourceBufferPrivateGStreamer(PassRefPtr<MediaSourceClientGStreamer>, const ContentType&); 47 virtual ~SourceBufferPrivateGStreamer(); 46 48 47 void setClient(SourceBufferPrivateClient*) { } 48 void append(const unsigned char*, unsigned); 49 void abort(); 50 void removedFromMediaSource(); 51 MediaPlayer::ReadyState readyState() const { return m_readyState; } 52 void setReadyState(MediaPlayer::ReadyState readyState) { m_readyState = readyState; } 53 void evictCodedFrames() { } 54 bool isFull() { return false; } 49 virtual void setClient(SourceBufferPrivateClient*); 50 51 virtual void append(const unsigned char* data, unsigned length); 52 virtual void abort(); 53 virtual void removedFromMediaSource(); 54 55 virtual MediaPlayer::ReadyState readyState() const; 56 virtual void setReadyState(MediaPlayer::ReadyState); 57 58 virtual void flushAndEnqueueNonDisplayingSamples(Vector<RefPtr<MediaSample>>, AtomicString); 59 virtual void enqueueSample(PassRefPtr<MediaSample>, AtomicString); 60 virtual bool isReadyForMoreSamples(AtomicString); 61 virtual void setActive(bool); 62 virtual void stopAskingForMoreSamples(AtomicString); 63 virtual void notifyClientWhenReadyForMoreSamples(AtomicString); 55 64 56 65 private: 57 String m_type; 58 RefPtr<MediaSourceClientGstreamer> m_client; 66 ContentType m_type; 67 RefPtr<MediaSourceClientGStreamer> m_client; 68 SourceBufferPrivateClient* m_sourceBufferPrivateClient; 59 69 MediaPlayer::ReadyState m_readyState; 60 70 }; -
trunk/Source/WebCore/platform/graphics/gstreamer/WebKitMediaSourceGStreamer.cpp
r176664 r177790 3 3 * Copyright (C) 2013 Collabora Ltd. 4 4 * Copyright (C) 2013 Orange 5 * Copyright (C) 2014 Sebastian Dröge <sebastian@centricular.com> 5 6 * 6 7 * This library is free software; you can redistribute it and/or … … 24 25 #if ENABLE(VIDEO) && ENABLE(MEDIA_SOURCE) && USE(GSTREAMER) 25 26 26 #include "GRefPtrGStreamer.h"27 27 #include "GStreamerUtilities.h" 28 28 #include "NotImplemented.h" 29 29 #include "TimeRanges.h" 30 30 31 #include <gst/app/gstappsrc.h> 31 32 #include <gst/gst.h> 32 33 #include <gst/pbutils/missing-plugins.h> 33 #include <wtf/gobject/GThreadSafeMainLoopSource.h>34 34 #include <wtf/gobject/GUniquePtr.h> 35 35 #include <wtf/text/CString.h> 36 36 37 typedef struct _Source { 38 GstElement* appsrc; 39 guint sourceid; /* To control the GSource */ 40 GstPad* srcpad; 41 gboolean padAdded; 42 43 guint64 offset; 44 guint64 size; 45 gboolean paused; 46 47 GThreadSafeMainLoopSource start; 48 GThreadSafeMainLoopSource stop; 49 GThreadSafeMainLoopSource needData; 50 GThreadSafeMainLoopSource enoughData; 51 GThreadSafeMainLoopSource seek; 52 53 guint64 requestedOffset; 54 } Source; 55 37 typedef struct _Source Source; 38 struct _Source { 39 GstElement* src; 40 // Just for identification 41 WebCore::SourceBufferPrivate* sourceBuffer; 42 }; 43 44 struct _WebKitMediaSrcPrivate { 45 GList* sources; 46 gchar* location; 47 GstClockTime duration; 48 bool haveAppsrc; 49 bool asyncStart; 50 bool noMorePads; 51 }; 52 53 enum { 54 Prop0, 55 PropLocation 56 }; 57 58 static GstStaticPadTemplate srcTemplate = GST_STATIC_PAD_TEMPLATE("src_%u", GST_PAD_SRC, 59 GST_PAD_SOMETIMES, GST_STATIC_CAPS_ANY); 56 60 57 61 #define WEBKIT_MEDIA_SRC_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), WEBKIT_TYPE_MEDIA_SRC, WebKitMediaSrcPrivate)) 58 59 struct _WebKitMediaSrcPrivate {60 gchar* uri;61 Source sourceVideo;62 Source sourceAudio;63 WebCore::MediaPlayer* player;64 GstElement* playbin;65 gint64 duration;66 gboolean seekable;67 gboolean noMorePad;68 // TRUE if appsrc's version is >= 0.10.27, see69 // https://bugzilla.gnome.org/show_bug.cgi?id=60942370 gboolean haveAppSrc27;71 guint nbSource;72 };73 74 enum {75 PropLocation = 1,76 ProLast77 };78 79 static GstStaticPadTemplate srcTemplate = GST_STATIC_PAD_TEMPLATE("src_%u", GST_PAD_SRC, GST_PAD_SOMETIMES, GST_STATIC_CAPS_ANY);80 62 81 63 GST_DEBUG_CATEGORY_STATIC(webkit_media_src_debug); … … 89 71 static gboolean webKitMediaSrcQueryWithParent(GstPad*, GstObject*, GstQuery*); 90 72 91 static void webKitMediaVideoSrcNeedDataCb(GstAppSrc*, guint, gpointer);92 static void webKitMediaVideoSrcEnoughDataCb(GstAppSrc*, gpointer);93 static gboolean webKitMediaVideoSrcSeekDataCb(GstAppSrc*, guint64, gpointer);94 static void webKitMediaAudioSrcNeedDataCb(GstAppSrc*, guint, gpointer);95 static void webKitMediaAudioSrcEnoughDataCb(GstAppSrc*, gpointer);96 static gboolean webKitMediaAudioSrcSeekDataCb(GstAppSrc*, guint64, gpointer);97 static GstAppSrcCallbacks appsrcCallbacksVideo = {98 webKitMediaVideoSrcNeedDataCb,99 webKitMediaVideoSrcEnoughDataCb,100 webKitMediaVideoSrcSeekDataCb,101 { 0 }102 };103 static GstAppSrcCallbacks appsrcCallbacksAudio = {104 webKitMediaAudioSrcNeedDataCb,105 webKitMediaAudioSrcEnoughDataCb,106 webKitMediaAudioSrcSeekDataCb,107 { 0 }108 };109 73 #define webkit_media_src_parent_class parent_class 110 74 // We split this out into another macro to avoid a check-webkit-style error. … … 125 89 gst_element_class_add_pad_template(eklass, gst_static_pad_template_get(&srcTemplate)); 126 90 127 gst_element_class_set_ metadata(eklass, "WebKit Media source element", "Source", "Handles Blob uris", "Stephane Jadaud <sjadaud@sii.fr>");91 gst_element_class_set_static_metadata(eklass, "WebKit Media source element", "Source", "Handles Blob uris", "Stephane Jadaud <sjadaud@sii.fr>, Sebastian Dröge <sebastian@centricular.com>"); 128 92 129 93 /* Allows setting the uri using the 'location' property, which is used … … 139 103 } 140 104 141 static void webKitMediaSrcAddSrc(WebKitMediaSrc* src, GstElement* element)142 {143 GstPad* ghostPad;144 WebKitMediaSrcPrivate* priv = src->priv;145 146 if (!gst_bin_add(GST_BIN(src), element)) {147 GST_DEBUG_OBJECT(src, "Src element not added");148 return;149 }150 GRefPtr<GstPad> targetsrc = adoptGRef(gst_element_get_static_pad(element, "src"));151 if (!targetsrc) {152 GST_DEBUG_OBJECT(src, "Pad not found");153 return;154 }155 156 gst_element_sync_state_with_parent(element);157 GUniquePtr<gchar> name(g_strdup_printf("src_%u", priv->nbSource));158 ghostPad = WebCore::webkitGstGhostPadFromStaticTemplate(&srcTemplate, name.get(), targetsrc.get());159 gst_pad_set_active(ghostPad, TRUE);160 161 priv->nbSource++;162 163 if (priv->sourceVideo.appsrc == element)164 priv->sourceVideo.srcpad = ghostPad;165 else if (priv->sourceAudio.appsrc == element)166 priv->sourceAudio.srcpad = ghostPad;167 168 GST_OBJECT_FLAG_SET(ghostPad, GST_PAD_FLAG_NEED_PARENT);169 gst_pad_set_query_function(ghostPad, webKitMediaSrcQueryWithParent);170 }171 172 105 static void webkit_media_src_init(WebKitMediaSrc* src) 173 106 { 174 WebKitMediaSrcPrivate* priv = WEBKIT_MEDIA_SRC_GET_PRIVATE(src); 175 src->priv = priv; 176 new (priv) WebKitMediaSrcPrivate(); 177 178 priv->sourceVideo.appsrc = gst_element_factory_make("appsrc", "videoappsrc"); 179 gst_app_src_set_callbacks(GST_APP_SRC(priv->sourceVideo.appsrc), &appsrcCallbacksVideo, src, 0); 180 gst_app_src_set_stream_type(GST_APP_SRC(priv->sourceVideo.appsrc), GST_APP_STREAM_TYPE_SEEKABLE); 181 webKitMediaSrcAddSrc(src, priv->sourceVideo.appsrc); 182 183 priv->sourceAudio.appsrc = gst_element_factory_make("appsrc", "audioappsrc"); 184 gst_app_src_set_callbacks(GST_APP_SRC(priv->sourceAudio.appsrc), &appsrcCallbacksAudio, src, 0); 185 gst_app_src_set_stream_type(GST_APP_SRC(priv->sourceAudio.appsrc), GST_APP_STREAM_TYPE_SEEKABLE); 186 webKitMediaSrcAddSrc(src, priv->sourceAudio.appsrc); 107 src->priv = WEBKIT_MEDIA_SRC_GET_PRIVATE(src); 187 108 } 188 109 … … 192 113 WebKitMediaSrcPrivate* priv = src->priv; 193 114 194 g_free(priv->uri);195 priv->~WebKitMediaSrcPrivate();115 // TODO: Free sources 116 g_free(priv->location); 196 117 197 118 GST_CALL_PARENT(G_OBJECT_CLASS, finalize, (object)); … … 201 122 { 202 123 WebKitMediaSrc* src = WEBKIT_MEDIA_SRC(object); 124 203 125 switch (propId) { 204 126 case PropLocation: … … 219 141 switch (propId) { 220 142 case PropLocation: 221 g_value_set_string(value, priv-> uri);143 g_value_set_string(value, priv->location); 222 144 break; 223 145 default: … … 228 150 } 229 151 230 // must be called on main thread and with object unlocked 231 static void webKitMediaVideoSrcStop(WebKitMediaSrc* src) 232 { 233 WebKitMediaSrcPrivate* priv = src->priv; 234 gboolean seeking; 235 236 GST_OBJECT_LOCK(src); 237 238 seeking = priv->sourceVideo.seek.isActive(); 239 240 priv->sourceVideo.start.cancel(); 241 242 priv->player = 0; 243 priv->playbin = 0; 244 245 priv->sourceVideo.needData.cancel(); 246 priv->sourceVideo.enoughData.cancel(); 247 priv->sourceVideo.seek.cancel(); 248 249 priv->sourceVideo.paused = FALSE; 250 priv->sourceVideo.offset = 0; 251 priv->seekable = FALSE; 252 253 priv->duration = 0; 254 priv->nbSource = 0; 255 256 GST_OBJECT_UNLOCK(src); 257 258 if (priv->sourceVideo.appsrc) { 259 gst_app_src_set_caps(GST_APP_SRC(priv->sourceVideo.appsrc), 0); 260 if (!seeking) 261 gst_app_src_set_size(GST_APP_SRC(priv->sourceVideo.appsrc), -1); 262 } 263 264 GST_DEBUG_OBJECT(src, "Stopped request"); 265 } 266 267 static void webKitMediaAudioSrcStop(WebKitMediaSrc* src) 268 { 269 WebKitMediaSrcPrivate* priv = src->priv; 270 gboolean seeking; 271 272 GST_OBJECT_LOCK(src); 273 274 seeking = priv->sourceAudio.seek.isActive(); 275 276 priv->sourceAudio.start.cancel(); 277 278 priv->player = 0; 279 280 priv->playbin = 0; 281 282 priv->sourceAudio.needData.cancel(); 283 priv->sourceAudio.enoughData.cancel(); 284 priv->sourceAudio.seek.cancel(); 285 286 priv->sourceAudio.paused = FALSE; 287 288 priv->sourceAudio.offset = 0; 289 290 priv->seekable = FALSE; 291 292 priv->duration = 0; 293 priv->nbSource = 0; 294 295 GST_OBJECT_UNLOCK(src); 296 297 if (priv->sourceAudio.appsrc) { 298 gst_app_src_set_caps(GST_APP_SRC(priv->sourceAudio.appsrc), 0); 299 if (!seeking) 300 gst_app_src_set_size(GST_APP_SRC(priv->sourceAudio.appsrc), -1); 301 } 302 303 GST_DEBUG_OBJECT(src, "Stopped request"); 304 } 305 306 // must be called on main thread and with object unlocked 307 static void webKitMediaVideoSrcStart(WebKitMediaSrc* src) 308 { 309 WebKitMediaSrcPrivate* priv = src->priv; 310 311 GST_OBJECT_LOCK(src); 312 if (!priv->uri) { 313 GST_ERROR_OBJECT(src, "No URI provided"); 314 GST_OBJECT_UNLOCK(src); 315 webKitMediaVideoSrcStop(src); 316 return; 317 } 318 319 GST_OBJECT_UNLOCK(src); 320 GST_DEBUG_OBJECT(src, "Started request"); 321 } 322 323 // must be called on main thread and with object unlocked 324 static void webKitMediaAudioSrcStart(WebKitMediaSrc* src) 325 { 326 WebKitMediaSrcPrivate* priv = src->priv; 327 328 GST_OBJECT_LOCK(src); 329 if (!priv->uri) { 330 GST_ERROR_OBJECT(src, "No URI provided"); 331 GST_OBJECT_UNLOCK(src); 332 webKitMediaAudioSrcStop(src); 333 return; 334 } 335 336 GST_OBJECT_UNLOCK(src); 337 GST_DEBUG_OBJECT(src, "Started request"); 152 static void webKitMediaSrcDoAsyncStart(WebKitMediaSrc* src) 153 { 154 WebKitMediaSrcPrivate* priv = src->priv; 155 priv->asyncStart = true; 156 GST_BIN_CLASS(parent_class)->handle_message(GST_BIN(src), 157 gst_message_new_async_start(GST_OBJECT(src))); 158 } 159 160 static void webKitMediaSrcDoAsyncDone(WebKitMediaSrc* src) 161 { 162 WebKitMediaSrcPrivate* priv = src->priv; 163 if (priv->asyncStart) { 164 GST_BIN_CLASS(parent_class)->handle_message(GST_BIN(src), 165 gst_message_new_async_done(GST_OBJECT(src), GST_CLOCK_TIME_NONE)); 166 priv->asyncStart = false; 167 } 338 168 } 339 169 … … 345 175 346 176 switch (transition) { 347 case GST_STATE_CHANGE_NULL_TO_READY: 348 if (!priv->sourceVideo.appsrc && !priv->sourceAudio.appsrc) { 349 gst_element_post_message(element, 350 gst_missing_element_message_new(element, "appsrc")); 351 GST_ELEMENT_ERROR(src, CORE, MISSING_PLUGIN, (0), ("no appsrc")); 352 return GST_STATE_CHANGE_FAILURE; 353 } 177 case GST_STATE_CHANGE_READY_TO_PAUSED: 178 priv->noMorePads = false; 179 webKitMediaSrcDoAsyncStart(src); 354 180 break; 355 181 default: … … 360 186 if (G_UNLIKELY(ret == GST_STATE_CHANGE_FAILURE)) { 361 187 GST_DEBUG_OBJECT(src, "State change failed"); 188 webKitMediaSrcDoAsyncDone(src); 362 189 return ret; 363 190 } … … 365 192 switch (transition) { 366 193 case GST_STATE_CHANGE_READY_TO_PAUSED: 367 GST_DEBUG_OBJECT(src, "READY->PAUSED"); 368 GST_OBJECT_LOCK(src); 369 370 gst_object_ref(src); 371 priv->sourceVideo.start.schedule("[WebKit] webKitMediaVideoSrcStart", std::function<void()>(std::bind(webKitMediaVideoSrcStart, src)), G_PRIORITY_DEFAULT, 372 [src] { gst_object_unref(src); }); 373 374 gst_object_ref(src); 375 priv->sourceAudio.start.schedule("[WebKit] webKitMediaAudioSrcStart", std::function<void()>(std::bind(webKitMediaAudioSrcStart, src)), G_PRIORITY_DEFAULT, 376 [src] { gst_object_unref(src); }); 377 378 GST_OBJECT_UNLOCK(src); 194 ret = GST_STATE_CHANGE_ASYNC; 379 195 break; 380 196 case GST_STATE_CHANGE_PAUSED_TO_READY: 381 GST_DEBUG_OBJECT(src, "PAUSED->READY"); 382 GST_OBJECT_LOCK(src); 383 384 gst_object_ref(src); 385 priv->sourceVideo.stop.schedule("[WebKit] webKitMediaVideoSrcStop", std::function<void()>(std::bind(webKitMediaVideoSrcStop, src)), G_PRIORITY_DEFAULT, 386 [src] { gst_object_unref(src); }); 387 388 gst_object_ref(src); 389 priv->sourceAudio.stop.schedule("[WebKit] webKitMediaAudioSrcStop", std::function<void()>(std::bind(webKitMediaAudioSrcStop, src)), G_PRIORITY_DEFAULT, 390 [src] { gst_object_unref(src); }); 391 392 GST_OBJECT_UNLOCK(src); 197 webKitMediaSrcDoAsyncDone(src); 198 priv->noMorePads = false; 393 199 break; 394 200 default: … … 420 226 case GST_QUERY_URI: { 421 227 GST_OBJECT_LOCK(src); 422 gst_query_set_uri(query, src->priv-> uri);228 gst_query_set_uri(query, src->priv->location); 423 229 GST_OBJECT_UNLOCK(src); 424 230 result = TRUE; … … 455 261 456 262 GST_OBJECT_LOCK(src); 457 ret = g_strdup(src->priv-> uri);263 ret = g_strdup(src->priv->location); 458 264 GST_OBJECT_UNLOCK(src); 459 265 return ret; … … 464 270 WebKitMediaSrc* src = WEBKIT_MEDIA_SRC(handler); 465 271 WebKitMediaSrcPrivate* priv = src->priv; 272 466 273 if (GST_STATE(src) >= GST_STATE_PAUSED) { 467 274 GST_ERROR_OBJECT(src, "URI can only be set in states < PAUSED"); … … 470 277 471 278 GST_OBJECT_LOCK(src); 472 g_free(priv-> uri);473 priv-> uri= 0;279 g_free(priv->location); 280 priv->location = 0; 474 281 if (!uri) { 475 282 GST_OBJECT_UNLOCK(src); … … 479 286 WebCore::URL url(WebCore::URL(), uri); 480 287 481 priv-> uri= g_strdup(url.string().utf8().data());288 priv->location = g_strdup(url.string().utf8().data()); 482 289 GST_OBJECT_UNLOCK(src); 483 290 return TRUE; 484 291 } 485 486 292 static void webKitMediaSrcUriHandlerInit(gpointer gIface, gpointer) 487 293 { … … 494 300 } 495 301 496 // appsrc callbacks 497 static void webKitMediaVideoSrcNeedDataMainCb(WebKitMediaSrc* src) 498 { 499 WebKitMediaSrcPrivate* priv = src->priv; 500 501 GST_OBJECT_LOCK(src); 502 priv->sourceVideo.paused = FALSE; 503 GST_OBJECT_UNLOCK(src); 504 } 505 506 static void webKitMediaAudioSrcNeedDataMainCb(WebKitMediaSrc* src) 507 { 508 WebKitMediaSrcPrivate* priv = src->priv; 509 510 GST_OBJECT_LOCK(src); 511 priv->sourceAudio.paused = FALSE; 512 GST_OBJECT_UNLOCK(src); 513 } 514 515 static void webKitMediaVideoSrcNeedDataCb(GstAppSrc*, guint length, gpointer userData) 516 { 517 WebKitMediaSrc* src = WEBKIT_MEDIA_SRC(userData); 518 WebKitMediaSrcPrivate* priv = src->priv; 519 520 GST_DEBUG_OBJECT(src, "Need more data: %u", length); 521 522 GST_OBJECT_LOCK(src); 523 if (priv->sourceVideo.needData.isScheduled() || !priv->sourceVideo.paused) { 524 GST_OBJECT_UNLOCK(src); 525 return; 526 } 527 528 gst_object_ref(src); 529 priv->sourceVideo.needData.schedule("[WebKit] webKitMediaVideoSrcNeedDataMainCb", std::function<void()>(std::bind(webKitMediaVideoSrcNeedDataMainCb, src)), G_PRIORITY_DEFAULT, 530 [src] { gst_object_unref(src); }); 531 GST_OBJECT_UNLOCK(src); 532 } 533 534 static void webKitMediaAudioSrcNeedDataCb(GstAppSrc*, guint length, gpointer userData) 535 { 536 WebKitMediaSrc* src = WEBKIT_MEDIA_SRC(userData); 537 WebKitMediaSrcPrivate* priv = src->priv; 538 539 GST_DEBUG_OBJECT(src, "Need more data: %u", length); 540 541 GST_OBJECT_LOCK(src); 542 if (priv->sourceAudio.needData.isScheduled() || !priv->sourceAudio.paused) { 543 GST_OBJECT_UNLOCK(src); 544 return; 545 } 546 547 gst_object_ref(src); 548 priv->sourceAudio.needData.schedule("[WebKit] webKitMediaAudioSrcNeedDataMainCb", std::function<void()>(std::bind(webKitMediaAudioSrcNeedDataMainCb, src)), G_PRIORITY_DEFAULT, 549 [src] { gst_object_unref(src); }); 550 GST_OBJECT_UNLOCK(src); 551 } 552 553 static void webKitMediaVideoSrcEnoughDataMainCb(WebKitMediaSrc* src) 554 { 555 WebKitMediaSrcPrivate* priv = src->priv; 556 557 GST_OBJECT_LOCK(src); 558 priv->sourceVideo.paused = TRUE; 559 GST_OBJECT_UNLOCK(src); 560 } 561 562 static void webKitMediaAudioSrcEnoughDataMainCb(WebKitMediaSrc* src) 563 { 564 WebKitMediaSrcPrivate* priv = src->priv; 565 566 GST_OBJECT_LOCK(src); 567 priv->sourceAudio.paused = TRUE; 568 GST_OBJECT_UNLOCK(src); 569 } 570 571 static void webKitMediaVideoSrcEnoughDataCb(GstAppSrc*, gpointer userData) 572 { 573 WebKitMediaSrc* src = WEBKIT_MEDIA_SRC(userData); 574 WebKitMediaSrcPrivate* priv = src->priv; 575 576 GST_DEBUG_OBJECT(src, "Have enough data"); 577 578 GST_OBJECT_LOCK(src); 579 if (priv->sourceVideo.enoughData.isScheduled() || priv->sourceVideo.paused) { 580 GST_OBJECT_UNLOCK(src); 581 return; 582 } 583 584 gst_object_ref(src); 585 priv->sourceVideo.enoughData.schedule("[WebKit] webKitMediaVideoSrcEnoughDataMainCb", std::function<void()>(std::bind(webKitMediaVideoSrcEnoughDataMainCb, src)), G_PRIORITY_DEFAULT, 586 [src] { gst_object_unref(src); }); 587 588 GST_OBJECT_UNLOCK(src); 589 } 590 591 static void webKitMediaAudioSrcEnoughDataCb(GstAppSrc*, gpointer userData) 592 { 593 WebKitMediaSrc* src = WEBKIT_MEDIA_SRC(userData); 594 WebKitMediaSrcPrivate* priv = src->priv; 595 596 GST_DEBUG_OBJECT(src, "Have enough data"); 597 598 GST_OBJECT_LOCK(src); 599 if (priv->sourceAudio.enoughData.isScheduled() || priv->sourceAudio.paused) { 600 GST_OBJECT_UNLOCK(src); 601 return; 602 } 603 604 gst_object_ref(src); 605 priv->sourceAudio.enoughData.schedule("[WebKit] webKitMediaAudioSrcEnoughDataMainCb", std::function<void()>(std::bind(webKitMediaAudioSrcEnoughDataMainCb, src)), G_PRIORITY_DEFAULT, 606 [src] { gst_object_unref(src); }); 607 608 GST_OBJECT_UNLOCK(src); 609 } 610 611 static void webKitMediaVideoSrcSeekMainCb(WebKitMediaSrc*) 612 { 613 notImplemented(); 614 } 615 616 617 static void webKitMediaAudioSrcSeekMainCb(WebKitMediaSrc*) 618 { 619 notImplemented(); 620 } 621 622 static gboolean webKitMediaVideoSrcSeekDataCb(GstAppSrc*, guint64 offset, gpointer userData) 623 { 624 WebKitMediaSrc* src = WEBKIT_MEDIA_SRC(userData); 625 WebKitMediaSrcPrivate* priv = src->priv; 626 627 GST_DEBUG_OBJECT(src, "Seeking to offset: %" G_GUINT64_FORMAT, offset); 628 GST_OBJECT_LOCK(src); 629 if (offset == priv->sourceVideo.offset && priv->sourceVideo.requestedOffset == priv->sourceVideo.offset) { 630 GST_OBJECT_UNLOCK(src); 631 return TRUE; 632 } 633 634 if (!priv->seekable) { 635 GST_OBJECT_UNLOCK(src); 636 return FALSE; 637 } 638 if (offset > priv->sourceVideo.size) { 639 GST_OBJECT_UNLOCK(src); 640 return FALSE; 641 } 642 643 GST_DEBUG_OBJECT(src, "Doing range-request seek"); 644 priv->sourceVideo.requestedOffset = offset; 645 646 gst_object_ref(src); 647 priv->sourceVideo.seek.schedule("[WebKit] webKitMediaVideoSrcSeekMainCb", std::function<void()>(std::bind(webKitMediaVideoSrcSeekMainCb, src)), G_PRIORITY_DEFAULT, 648 [src] { gst_object_unref(src); }); 649 650 GST_OBJECT_UNLOCK(src); 651 652 return TRUE; 653 } 654 655 static gboolean webKitMediaAudioSrcSeekDataCb(GstAppSrc*, guint64 offset, gpointer userData) 656 { 657 WebKitMediaSrc* src = WEBKIT_MEDIA_SRC(userData); 658 WebKitMediaSrcPrivate* priv = src->priv; 659 660 GST_DEBUG_OBJECT(src, "Seeking to offset: %" G_GUINT64_FORMAT, offset); 661 GST_OBJECT_LOCK(src); 662 if (offset == priv->sourceAudio.offset && priv->sourceAudio.requestedOffset == priv->sourceAudio.offset) { 663 GST_OBJECT_UNLOCK(src); 664 return TRUE; 665 } 666 667 if (!priv->seekable) { 668 GST_OBJECT_UNLOCK(src); 669 return FALSE; 670 } 671 if (offset > priv->sourceAudio.size) { 672 GST_OBJECT_UNLOCK(src); 673 return FALSE; 674 } 675 676 GST_DEBUG_OBJECT(src, "Doing range-request seek"); 677 priv->sourceAudio.requestedOffset = offset; 678 679 gst_object_ref(src); 680 priv->sourceAudio.seek.schedule("[WebKit] webKitMediaAudioSrcSeekMainCb", std::function<void()>(std::bind(webKitMediaAudioSrcSeekMainCb, src)), G_PRIORITY_DEFAULT, 681 [src] { gst_object_unref(src); }); 682 683 GST_OBJECT_UNLOCK(src); 684 685 return TRUE; 686 } 687 688 void webKitMediaSrcSetMediaPlayer(WebKitMediaSrc* src, WebCore::MediaPlayer* player) 689 { 690 WebKitMediaSrcPrivate* priv = src->priv; 691 priv->player = player; 692 } 693 694 void webKitMediaSrcSetPlayBin(WebKitMediaSrc* src, GstElement* playBin) 695 { 696 WebKitMediaSrcPrivate* priv = src->priv; 697 priv->playbin = playBin; 698 } 699 700 MediaSourceClientGstreamer::MediaSourceClientGstreamer(WebKitMediaSrc* src) 701 : m_src(static_cast<WebKitMediaSrc*>(gst_object_ref(src))) 702 { 703 } 704 705 MediaSourceClientGstreamer::~MediaSourceClientGstreamer() 706 { 707 gst_object_unref(m_src); 708 } 709 710 void MediaSourceClientGstreamer::didReceiveDuration(double duration) 302 namespace WebCore { 303 MediaSourceClientGStreamer::MediaSourceClientGStreamer(WebKitMediaSrc* src) 304 : m_src(adoptGRef(static_cast<WebKitMediaSrc*>(gst_object_ref(src)))) 305 { 306 } 307 308 MediaSourceClientGStreamer::~MediaSourceClientGStreamer() 309 { 310 } 311 312 MediaSourcePrivate::AddStatus MediaSourceClientGStreamer::addSourceBuffer(PassRefPtr<SourceBufferPrivate> sourceBufferPrivate, const ContentType&) 711 313 { 712 314 WebKitMediaSrcPrivate* priv = m_src->priv; 713 GST_DEBUG_OBJECT(m_src, "Received duration: %lf", duration); 714 715 GST_OBJECT_LOCK(m_src); 716 priv->duration = duration >= 0.0 ? static_cast<gint64>(duration*GST_SECOND) : 0; 717 GST_OBJECT_UNLOCK(m_src); 718 } 719 720 void MediaSourceClientGstreamer::didReceiveData(const char* data, int length, String type) 315 316 if (priv->noMorePads) { 317 GST_ERROR_OBJECT(m_src.get(), "Adding new source buffers after first data not supported yet"); 318 return MediaSourcePrivate::NotSupported; 319 } 320 321 GST_DEBUG_OBJECT(m_src.get(), "State %d", static_cast<int>(GST_STATE(m_src.get()))); 322 323 GST_OBJECT_LOCK(m_src.get()); 324 325 Source* source = g_new0(Source, 1); 326 guint numberOfSources = g_list_length(priv->sources); 327 GUniquePtr<gchar> srcName(g_strdup_printf("src%u", numberOfSources)); 328 329 source->src = gst_element_factory_make("appsrc", srcName.get()); 330 source->sourceBuffer = sourceBufferPrivate.get(); 331 332 GUniquePtr<gchar> padName(g_strdup_printf("src_%u", numberOfSources)); 333 priv->sources = g_list_prepend(priv->sources, source); 334 GST_OBJECT_UNLOCK(m_src.get()); 335 336 priv->haveAppsrc = source->src; 337 338 gst_bin_add(GST_BIN(m_src.get()), source->src); 339 GRefPtr<GstPad> pad = adoptGRef(gst_element_get_static_pad(source->src, "src")); 340 GRefPtr<GstPad> ghostPad = adoptGRef(gst_ghost_pad_new_from_template(padName.get(), pad.get(), 341 gst_static_pad_template_get(&srcTemplate))); 342 gst_pad_set_query_function(ghostPad.get(), webKitMediaSrcQueryWithParent); 343 gst_pad_set_active(ghostPad.get(), TRUE); 344 gst_element_add_pad(GST_ELEMENT(m_src.get()), ghostPad.leakRef()); 345 346 gst_element_sync_state_with_parent(source->src); 347 348 return MediaSourcePrivate::Ok; 349 } 350 351 void MediaSourceClientGStreamer::durationChanged(const MediaTime& duration) 352 { 353 WebKitMediaSrcPrivate* priv = m_src->priv; 354 GstClockTime gstDuration = gst_util_uint64_scale(duration.timeValue(), GST_SECOND, duration.timeScale()); 355 356 GST_DEBUG_OBJECT(m_src.get(), "Received duration: %" GST_TIME_FORMAT, GST_TIME_ARGS(gstDuration)); 357 358 GST_OBJECT_LOCK(m_src.get()); 359 priv->duration = gstDuration; 360 GST_OBJECT_UNLOCK(m_src.get()); 361 gst_element_post_message(GST_ELEMENT(m_src.get()), gst_message_new_duration_changed(GST_OBJECT(m_src.get()))); 362 } 363 364 SourceBufferPrivateClient::AppendResult MediaSourceClientGStreamer::append(PassRefPtr<SourceBufferPrivate> sourceBufferPrivate, const unsigned char* data, unsigned length) 721 365 { 722 366 WebKitMediaSrcPrivate* priv = m_src->priv; 723 367 GstFlowReturn ret = GST_FLOW_OK; 724 GstBuffer * buffer; 725 726 if (type.startsWith("video")) { 727 if (priv->noMorePad == FALSE && priv->sourceVideo.padAdded == TRUE) { 728 gst_element_no_more_pads(GST_ELEMENT(m_src)); 729 priv->noMorePad = TRUE; 368 GstBuffer* buffer; 369 Source* source = 0; 370 371 if (!priv->noMorePads) { 372 priv->noMorePads = true; 373 gst_element_no_more_pads(GST_ELEMENT(m_src.get())); 374 webKitMediaSrcDoAsyncDone(m_src.get()); 375 } 376 377 for (GList* iter = priv->sources; iter; iter = iter->next) { 378 Source* tmp = static_cast<Source*>(iter->data); 379 if (tmp->sourceBuffer == sourceBufferPrivate.get()) { 380 source = tmp; 381 break; 730 382 } 731 if (priv->noMorePad == FALSE && priv->sourceVideo.padAdded == FALSE) { 732 gst_element_add_pad(GST_ELEMENT(m_src), priv->sourceVideo.srcpad); 733 priv->sourceVideo.padAdded = TRUE; 383 } 384 385 if (!source || !source->src) 386 return SourceBufferPrivateClient::ReadStreamFailed; 387 388 buffer = gst_buffer_new_and_alloc(length); 389 gst_buffer_fill(buffer, 0, data, length); 390 391 ret = gst_app_src_push_buffer(GST_APP_SRC(source->src), buffer); 392 GST_DEBUG_OBJECT(m_src.get(), "push buffer %d\n", static_cast<int>(ret)); 393 394 if (ret == GST_FLOW_OK) 395 return SourceBufferPrivateClient::AppendSucceeded; 396 397 return SourceBufferPrivateClient::ReadStreamFailed; 398 } 399 400 void MediaSourceClientGStreamer::markEndOfStream(MediaSourcePrivate::EndOfStreamStatus) 401 { 402 WebKitMediaSrcPrivate* priv = m_src->priv; 403 404 GST_DEBUG_OBJECT(m_src.get(), "Have EOS"); 405 406 if (!priv->noMorePads) { 407 priv->noMorePads = true; 408 gst_element_no_more_pads(GST_ELEMENT(m_src.get())); 409 webKitMediaSrcDoAsyncDone(m_src.get()); 410 } 411 412 for (GList* iter = priv->sources; iter; iter = iter->next) { 413 Source* source = static_cast<Source*>(iter->data); 414 if (source->src) 415 gst_app_src_end_of_stream(GST_APP_SRC(source->src)); 416 } 417 } 418 419 void MediaSourceClientGStreamer::removedFromMediaSource(PassRefPtr<SourceBufferPrivate> sourceBufferPrivate) 420 { 421 WebKitMediaSrcPrivate* priv = m_src->priv; 422 Source* source = 0; 423 424 for (GList* iter = priv->sources; iter; iter = iter->next) { 425 Source* tmp = static_cast<Source*>(iter->data); 426 if (tmp->sourceBuffer == sourceBufferPrivate.get()) { 427 source = tmp; 428 break; 734 429 } 735 GST_OBJECT_LOCK(m_src); 736 buffer = WebCore::createGstBufferForData(data, length); 737 GST_OBJECT_UNLOCK(m_src); 738 739 ret = gst_app_src_push_buffer(GST_APP_SRC(priv->sourceVideo.appsrc), buffer); 740 } else if (type.startsWith("audio")) { 741 if (priv->noMorePad == FALSE && priv->sourceAudio.padAdded == TRUE) { 742 gst_element_no_more_pads(GST_ELEMENT(m_src)); 743 priv->noMorePad = TRUE; 744 } 745 if (priv->noMorePad == FALSE && priv->sourceAudio.padAdded == FALSE) { 746 gst_element_add_pad(GST_ELEMENT(m_src), priv->sourceAudio.srcpad); 747 priv->sourceAudio.padAdded = TRUE; 748 } 749 GST_OBJECT_LOCK(m_src); 750 buffer = WebCore::createGstBufferForData(data, length); 751 GST_OBJECT_UNLOCK(m_src); 752 753 ret = gst_app_src_push_buffer(GST_APP_SRC(priv->sourceAudio.appsrc), buffer); 754 } 755 756 if (ret != GST_FLOW_OK && ret != GST_FLOW_EOS) 757 GST_ELEMENT_ERROR(m_src, CORE, FAILED, (0), (0)); 758 } 759 760 void MediaSourceClientGstreamer::didFinishLoading(double) 761 { 762 WebKitMediaSrcPrivate* priv = m_src->priv; 763 764 GST_DEBUG_OBJECT(m_src, "Have EOS"); 765 766 GST_OBJECT_LOCK(m_src); 767 if (!priv->sourceVideo.seek.isActive()) { 768 GST_OBJECT_UNLOCK(m_src); 769 gst_app_src_end_of_stream(GST_APP_SRC(priv->sourceVideo.appsrc)); 770 } else 771 GST_OBJECT_UNLOCK(m_src); 772 773 GST_OBJECT_LOCK(m_src); 774 if (!priv->sourceAudio.seek.isActive()) { 775 GST_OBJECT_UNLOCK(m_src); 776 gst_app_src_end_of_stream(GST_APP_SRC(priv->sourceAudio.appsrc)); 777 } else 778 GST_OBJECT_UNLOCK(m_src); 779 } 780 781 void MediaSourceClientGstreamer::didFail() 782 { 783 gst_app_src_end_of_stream(GST_APP_SRC(m_src->priv->sourceVideo.appsrc)); 784 gst_app_src_end_of_stream(GST_APP_SRC(m_src->priv->sourceAudio.appsrc)); 785 } 430 } 431 432 ASSERT(source && source->src); 433 434 gst_app_src_end_of_stream(GST_APP_SRC(source->src)); 435 } 436 437 }; 438 439 namespace WTF { 440 template <> GRefPtr<WebKitMediaSrc> adoptGRef(WebKitMediaSrc* ptr) 441 { 442 ASSERT(!ptr || !g_object_is_floating(G_OBJECT(ptr))); 443 return GRefPtr<WebKitMediaSrc>(ptr, GRefPtrAdopt); 444 } 445 446 template <> WebKitMediaSrc* refGPtr<WebKitMediaSrc>(WebKitMediaSrc* ptr) 447 { 448 if (ptr) 449 gst_object_ref_sink(GST_OBJECT(ptr)); 450 451 return ptr; 452 } 453 454 template <> void derefGPtr<WebKitMediaSrc>(WebKitMediaSrc* ptr) 455 { 456 if (ptr) 457 gst_object_unref(ptr); 458 } 459 }; 786 460 787 461 #endif // USE(GSTREAMER) -
trunk/Source/WebCore/platform/graphics/gstreamer/WebKitMediaSourceGStreamer.h
r159335 r177790 3 3 * Copyright (C) 2013 Collabora Ltd. 4 4 * Copyright (C) 2013 Orange 5 * Copyright (C) 2014 Sebastian Dröge <sebastian@centricular.com> 5 6 * 6 7 * This library is free software; you can redistribute it and/or … … 23 24 #if ENABLE(VIDEO) && ENABLE(MEDIA_SOURCE) && USE(GSTREAMER) 24 25 26 #include "GRefPtrGStreamer.h" 25 27 #include "MediaPlayer.h" 28 #include "MediaSource.h" 29 #include "SourceBufferPrivate.h" 30 #include "SourceBufferPrivateClient.h" 31 26 32 #include <gst/gst.h> 27 33 … … 49 55 50 56 GType webkit_media_src_get_type(void); 51 void webKitMediaSrcSetMediaPlayer(WebKitMediaSrc*, WebCore::MediaPlayer*);52 void webKitMediaSrcSetPlayBin(WebKitMediaSrc*, GstElement*);53 57 54 58 G_END_DECLS 55 59 56 class MediaSourceClientGstreamer: public RefCounted<MediaSourceClientGstreamer> { 60 namespace WTF { 61 template<> GRefPtr<WebKitMediaSrc> adoptGRef(WebKitMediaSrc* ptr); 62 template<> WebKitMediaSrc* refGPtr<WebKitMediaSrc>(WebKitMediaSrc* ptr); 63 template<> void derefGPtr<WebKitMediaSrc>(WebKitMediaSrc* ptr); 64 }; 65 66 namespace WebCore { 67 68 class ContentType; 69 70 class MediaSourceClientGStreamer: public RefCounted<MediaSourceClientGStreamer> { 57 71 public: 58 MediaSourceClientG streamer(WebKitMediaSrc*);59 ~MediaSourceClientGstreamer();72 MediaSourceClientGStreamer(WebKitMediaSrc*); 73 virtual ~MediaSourceClientGStreamer(); 60 74 61 void didReceiveDuration(double); 62 void didReceiveData(const char*, int, String); 63 void didFinishLoading(double); 64 void didFail(); 75 // From MediaSourceGStreamer 76 MediaSourcePrivate::AddStatus addSourceBuffer(PassRefPtr<SourceBufferPrivate>, const ContentType&); 77 void durationChanged(const MediaTime&); 78 void markEndOfStream(MediaSourcePrivate::EndOfStreamStatus); 79 80 // From SourceBufferPrivateGStreamer 81 SourceBufferPrivateClient::AppendResult append(PassRefPtr<SourceBufferPrivate>, const unsigned char*, unsigned); 82 void removedFromMediaSource(PassRefPtr<SourceBufferPrivate>); 65 83 66 84 private: 67 WebKitMediaSrc*m_src;85 GRefPtr<WebKitMediaSrc> m_src; 68 86 }; 69 87 88 }; 70 89 71 90 #endif // USE(GSTREAMER)
Note: See TracChangeset
for help on using the changeset viewer.