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 (size_t i = 0; i < tracks.size(); ++i) { | |
haraken
2017/03/06 18:37:29
iterator is preferred, since tracks[i] involves CH
mcasas
2017/03/06 19:38:59
Oh I thought WebVector didn't have iterators. Awes
| |
57 tracks[i]->stopTrack(ASSERT_NO_EXCEPTION); | |
58 m_mediaStream->removeTrackByComponent(tracks[i]->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 (size_t i = 0; i < videoTracks.size(); ++i) | |
haraken
2017/03/06 18:37:29
Ditto.
mcasas
2017/03/06 19:38:59
Done.
| |
83 m_mediaStream->addTrackByComponent(videoTracks[i]); | |
84 | |
85 WebVector<WebMediaStreamTrack> audioTracks; | |
86 webStream.audioTracks(audioTracks); | |
87 for (size_t i = 0; i < audioTracks.size(); ++i) | |
haraken
2017/03/06 18:37:29
Ditto.
mcasas
2017/03/06 19:38:59
Done.
| |
88 m_mediaStream->addTrackByComponent(audioTracks[i]); | |
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 |