OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "modules/mediacapturefromelement/HTMLMediaElementCapture.h" | 5 #include "modules/mediacapturefromelement/HTMLMediaElementCapture.h" |
6 | 6 |
7 #include "core/dom/ExceptionCode.h" | 7 #include "core/dom/ExceptionCode.h" |
| 8 #include "core/events/EventListener.h" |
8 #include "core/html/HTMLMediaElement.h" | 9 #include "core/html/HTMLMediaElement.h" |
9 #include "core/html/track/AudioTrackList.h" | 10 #include "core/html/track/AudioTrackList.h" |
10 #include "core/html/track/VideoTrackList.h" | 11 #include "core/html/track/VideoTrackList.h" |
11 #include "modules/encryptedmedia/HTMLMediaElementEncryptedMedia.h" | 12 #include "modules/encryptedmedia/HTMLMediaElementEncryptedMedia.h" |
12 #include "modules/encryptedmedia/MediaKeys.h" | 13 #include "modules/encryptedmedia/MediaKeys.h" |
13 #include "modules/mediastream/MediaStream.h" | 14 #include "modules/mediastream/MediaStream.h" |
14 #include "modules/mediastream/MediaStreamRegistry.h" | 15 #include "modules/mediastream/MediaStreamRegistry.h" |
15 #include "platform/mediastream/MediaStreamCenter.h" | 16 #include "platform/mediastream/MediaStreamCenter.h" |
16 #include "public/platform/Platform.h" | 17 #include "public/platform/Platform.h" |
17 #include "public/platform/WebMediaStream.h" | 18 #include "public/platform/WebMediaStream.h" |
18 #include "public/platform/WebMediaStreamTrack.h" | 19 #include "public/platform/WebMediaStreamTrack.h" |
19 | 20 |
20 namespace blink { | 21 namespace blink { |
21 | 22 |
| 23 namespace { |
| 24 |
| 25 // Class to register to the events of |m_mediaElement|, acting accordingly on |
| 26 // the tracks of |m_mediaStream|. |
| 27 class MediaElementEventListener final : public EventListener { |
| 28 WTF_MAKE_NONCOPYABLE(MediaElementEventListener); |
| 29 |
| 30 public: |
| 31 MediaElementEventListener(HTMLMediaElement* element, MediaStream* stream) |
| 32 : EventListener(CPPEventListenerType), |
| 33 m_mediaElement(element), |
| 34 m_mediaStream(stream) {} |
| 35 |
| 36 DECLARE_VIRTUAL_TRACE(); |
| 37 |
| 38 private: |
| 39 // EventListener implementation. |
| 40 void handleEvent(ExecutionContext*, Event*) override; |
| 41 bool operator==(const EventListener& other) const override { |
| 42 return this == &other; |
| 43 } |
| 44 |
| 45 Member<HTMLMediaElement> m_mediaElement; |
| 46 Member<MediaStream> m_mediaStream; |
| 47 }; |
| 48 |
| 49 void MediaElementEventListener::handleEvent(ExecutionContext* context, |
| 50 Event* event) { |
| 51 DVLOG(2) << __func__ << " " << event->type(); |
| 52 DCHECK(m_mediaStream); |
| 53 |
| 54 if (event->type() == EventTypeNames::ended) { |
| 55 MediaStreamTrackVector tracks = m_mediaStream->getTracks(); |
| 56 for (const auto& track : tracks) { |
| 57 track->stopTrack(ASSERT_NO_EXCEPTION); |
| 58 m_mediaStream->removeTrackByComponent(track->component()); |
| 59 } |
| 60 |
| 61 m_mediaStream->streamEnded(); |
| 62 return; |
| 63 } |
| 64 if (event->type() != EventTypeNames::loadedmetadata) |
| 65 return; |
| 66 |
| 67 WebMediaStream webStream; |
| 68 webStream.initialize(WebVector<WebMediaStreamTrack>(), |
| 69 WebVector<WebMediaStreamTrack>()); |
| 70 |
| 71 if (m_mediaElement->hasVideo()) { |
| 72 Platform::current()->createHTMLVideoElementCapturer( |
| 73 &webStream, m_mediaElement->webMediaPlayer()); |
| 74 } |
| 75 if (m_mediaElement->hasAudio()) { |
| 76 Platform::current()->createHTMLAudioElementCapturer( |
| 77 &webStream, m_mediaElement->webMediaPlayer()); |
| 78 } |
| 79 |
| 80 WebVector<WebMediaStreamTrack> videoTracks; |
| 81 webStream.videoTracks(videoTracks); |
| 82 for (const auto& track : videoTracks) |
| 83 m_mediaStream->addTrackByComponent(track); |
| 84 |
| 85 WebVector<WebMediaStreamTrack> audioTracks; |
| 86 webStream.audioTracks(audioTracks); |
| 87 for (const auto& track : audioTracks) |
| 88 m_mediaStream->addTrackByComponent(track); |
| 89 |
| 90 DVLOG(2) << "#videotracks: " << videoTracks.size() |
| 91 << " #audiotracks: " << audioTracks.size(); |
| 92 } |
| 93 |
| 94 DEFINE_TRACE(MediaElementEventListener) { |
| 95 visitor->trace(m_mediaElement); |
| 96 visitor->trace(m_mediaStream); |
| 97 EventListener::trace(visitor); |
| 98 } |
| 99 |
| 100 } // anonymous namespace |
| 101 |
22 // static | 102 // static |
23 MediaStream* HTMLMediaElementCapture::captureStream( | 103 MediaStream* HTMLMediaElementCapture::captureStream( |
24 HTMLMediaElement& element, | 104 HTMLMediaElement& element, |
25 ExceptionState& exceptionState) { | 105 ExceptionState& exceptionState) { |
26 if (element.currentSrc().isNull()) { | |
27 exceptionState.throwDOMException(NotSupportedError, | |
28 "The media element must have a source."); | |
29 return nullptr; | |
30 } | |
31 | |
32 // Avoid capturing from EME-protected Media Elements. | 106 // Avoid capturing from EME-protected Media Elements. |
33 if (HTMLMediaElementEncryptedMedia::mediaKeys(element)) { | 107 if (HTMLMediaElementEncryptedMedia::mediaKeys(element)) { |
34 // This exception is not defined in the spec, see | 108 // This exception is not defined in the spec, see |
35 // https://github.com/w3c/mediacapture-fromelement/issues/20. | 109 // https://github.com/w3c/mediacapture-fromelement/issues/20. |
36 exceptionState.throwDOMException(NotSupportedError, | 110 exceptionState.throwDOMException(NotSupportedError, |
37 "Stream capture not supported with EME"); | 111 "Stream capture not supported with EME"); |
38 return nullptr; | 112 return nullptr; |
39 } | 113 } |
40 | 114 |
| 115 WebMediaStream webStream; |
| 116 webStream.initialize(WebVector<WebMediaStreamTrack>(), |
| 117 WebVector<WebMediaStreamTrack>()); |
| 118 |
| 119 // create() duplicates the MediaStreamTracks inside |webStream|. |
| 120 MediaStream* stream = |
| 121 MediaStream::create(element.getExecutionContext(), webStream); |
| 122 |
| 123 EventListener* listener = new MediaElementEventListener(&element, stream); |
| 124 element.addEventListener(EventTypeNames::loadedmetadata, listener, false); |
| 125 element.addEventListener(EventTypeNames::ended, listener, false); |
| 126 |
41 // If |element| is actually playing a MediaStream, just clone it. | 127 // If |element| is actually playing a MediaStream, just clone it. |
42 if (HTMLMediaElement::isMediaStreamURL(element.currentSrc().getString())) { | 128 if (!element.currentSrc().isNull() && |
| 129 HTMLMediaElement::isMediaStreamURL(element.currentSrc().getString())) { |
43 return MediaStream::create( | 130 return MediaStream::create( |
44 element.getExecutionContext(), | 131 element.getExecutionContext(), |
45 MediaStreamRegistry::registry().lookupMediaStreamDescriptor( | 132 MediaStreamRegistry::registry().lookupMediaStreamDescriptor( |
46 element.currentSrc().getString())); | 133 element.currentSrc().getString())); |
47 } | 134 } |
48 | 135 |
49 WebMediaStream webStream; | 136 if (element.hasVideo()) { |
50 webStream.initialize(WebVector<WebMediaStreamTrack>(), | |
51 WebVector<WebMediaStreamTrack>()); | |
52 MediaStreamCenter::instance().didCreateMediaStream(webStream); | |
53 | |
54 if (element.hasVideo()) | |
55 Platform::current()->createHTMLVideoElementCapturer( | 137 Platform::current()->createHTMLVideoElementCapturer( |
56 &webStream, element.webMediaPlayer()); | 138 &webStream, element.webMediaPlayer()); |
57 if (element.hasAudio()) | 139 } |
| 140 if (element.hasAudio()) { |
58 Platform::current()->createHTMLAudioElementCapturer( | 141 Platform::current()->createHTMLAudioElementCapturer( |
59 &webStream, element.webMediaPlayer()); | 142 &webStream, element.webMediaPlayer()); |
60 return MediaStream::create(element.getExecutionContext(), webStream); | 143 } |
| 144 |
| 145 // If element.currentSrc().isNull() then |stream| will have no tracks, those |
| 146 // will be added eventually afterwards via MediaElementEventListener. |
| 147 return stream; |
61 } | 148 } |
62 | 149 |
63 } // namespace blink | 150 } // namespace blink |
OLD | NEW |