Index: third_party/WebKit/Source/modules/mediacapturefromelement/HTMLMediaElementCapture.cpp |
diff --git a/third_party/WebKit/Source/modules/mediacapturefromelement/HTMLMediaElementCapture.cpp b/third_party/WebKit/Source/modules/mediacapturefromelement/HTMLMediaElementCapture.cpp |
index 53b90572d80ae6893decad49b02d28ac6807d988..9909805c8322b6132b47390cec5c87fc35f77423 100644 |
--- a/third_party/WebKit/Source/modules/mediacapturefromelement/HTMLMediaElementCapture.cpp |
+++ b/third_party/WebKit/Source/modules/mediacapturefromelement/HTMLMediaElementCapture.cpp |
@@ -5,6 +5,7 @@ |
#include "modules/mediacapturefromelement/HTMLMediaElementCapture.h" |
#include "core/dom/ExceptionCode.h" |
+#include "core/events/EventListener.h" |
#include "core/html/HTMLMediaElement.h" |
#include "core/html/track/AudioTrackList.h" |
#include "core/html/track/VideoTrackList.h" |
@@ -19,16 +20,89 @@ |
namespace blink { |
+namespace { |
+ |
+// Class to register to the events of |m_mediaElement|, acting accordingly on |
+// the tracks of |m_mediaStream|. |
+class MediaElementEventListener final : public EventListener { |
+ WTF_MAKE_NONCOPYABLE(MediaElementEventListener); |
+ |
+ public: |
+ MediaElementEventListener(HTMLMediaElement* element, MediaStream* stream) |
+ : EventListener(CPPEventListenerType), |
+ m_mediaElement(element), |
+ m_mediaStream(stream) {} |
+ |
+ DECLARE_VIRTUAL_TRACE(); |
+ |
+ private: |
+ // EventListener implementation. |
+ void handleEvent(ExecutionContext*, Event*) override; |
+ bool operator==(const EventListener& other) const override { |
+ return this == &other; |
+ } |
+ |
+ Member<HTMLMediaElement> m_mediaElement; |
+ Member<MediaStream> m_mediaStream; |
+}; |
+ |
+void MediaElementEventListener::handleEvent(ExecutionContext* context, |
+ Event* event) { |
+ DVLOG(2) << __func__ << " " << event->type(); |
+ DCHECK(m_mediaStream); |
+ |
+ if (event->type() == EventTypeNames::ended) { |
+ MediaStreamTrackVector tracks = m_mediaStream->getTracks(); |
+ for (const auto& track : tracks) { |
+ track->stopTrack(ASSERT_NO_EXCEPTION); |
+ m_mediaStream->removeTrackByComponent(track->component()); |
+ } |
+ |
+ m_mediaStream->streamEnded(); |
+ return; |
+ } |
+ if (event->type() != EventTypeNames::loadedmetadata) |
+ return; |
+ |
+ WebMediaStream webStream; |
+ webStream.initialize(WebVector<WebMediaStreamTrack>(), |
+ WebVector<WebMediaStreamTrack>()); |
+ |
+ if (m_mediaElement->hasVideo()) { |
+ Platform::current()->createHTMLVideoElementCapturer( |
+ &webStream, m_mediaElement->webMediaPlayer()); |
+ } |
+ if (m_mediaElement->hasAudio()) { |
+ Platform::current()->createHTMLAudioElementCapturer( |
+ &webStream, m_mediaElement->webMediaPlayer()); |
+ } |
+ |
+ WebVector<WebMediaStreamTrack> videoTracks; |
+ webStream.videoTracks(videoTracks); |
+ for (const auto& track : videoTracks) |
+ m_mediaStream->addTrackByComponent(track); |
+ |
+ WebVector<WebMediaStreamTrack> audioTracks; |
+ webStream.audioTracks(audioTracks); |
+ for (const auto& track : audioTracks) |
+ m_mediaStream->addTrackByComponent(track); |
+ |
+ DVLOG(2) << "#videotracks: " << videoTracks.size() |
+ << " #audiotracks: " << audioTracks.size(); |
+} |
+ |
+DEFINE_TRACE(MediaElementEventListener) { |
+ visitor->trace(m_mediaElement); |
+ visitor->trace(m_mediaStream); |
+ EventListener::trace(visitor); |
+} |
+ |
+} // anonymous namespace |
+ |
// static |
MediaStream* HTMLMediaElementCapture::captureStream( |
HTMLMediaElement& element, |
ExceptionState& exceptionState) { |
- if (element.currentSrc().isNull()) { |
- exceptionState.throwDOMException(NotSupportedError, |
- "The media element must have a source."); |
- return nullptr; |
- } |
- |
// Avoid capturing from EME-protected Media Elements. |
if (HTMLMediaElementEncryptedMedia::mediaKeys(element)) { |
// This exception is not defined in the spec, see |
@@ -38,26 +112,39 @@ MediaStream* HTMLMediaElementCapture::captureStream( |
return nullptr; |
} |
+ WebMediaStream webStream; |
+ webStream.initialize(WebVector<WebMediaStreamTrack>(), |
+ WebVector<WebMediaStreamTrack>()); |
+ |
+ // create() duplicates the MediaStreamTracks inside |webStream|. |
+ MediaStream* stream = |
+ MediaStream::create(element.getExecutionContext(), webStream); |
+ |
+ EventListener* listener = new MediaElementEventListener(&element, stream); |
+ element.addEventListener(EventTypeNames::loadedmetadata, listener, false); |
+ element.addEventListener(EventTypeNames::ended, listener, false); |
+ |
// If |element| is actually playing a MediaStream, just clone it. |
- if (HTMLMediaElement::isMediaStreamURL(element.currentSrc().getString())) { |
+ if (!element.currentSrc().isNull() && |
+ HTMLMediaElement::isMediaStreamURL(element.currentSrc().getString())) { |
return MediaStream::create( |
element.getExecutionContext(), |
MediaStreamRegistry::registry().lookupMediaStreamDescriptor( |
element.currentSrc().getString())); |
} |
- WebMediaStream webStream; |
- webStream.initialize(WebVector<WebMediaStreamTrack>(), |
- WebVector<WebMediaStreamTrack>()); |
- MediaStreamCenter::instance().didCreateMediaStream(webStream); |
- |
- if (element.hasVideo()) |
+ if (element.hasVideo()) { |
Platform::current()->createHTMLVideoElementCapturer( |
&webStream, element.webMediaPlayer()); |
- if (element.hasAudio()) |
+ } |
+ if (element.hasAudio()) { |
Platform::current()->createHTMLAudioElementCapturer( |
&webStream, element.webMediaPlayer()); |
- return MediaStream::create(element.getExecutionContext(), webStream); |
+ } |
+ |
+ // If element.currentSrc().isNull() then |stream| will have no tracks, those |
+ // will be added eventually afterwards via MediaElementEventListener. |
+ return stream; |
} |
} // namespace blink |