Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(183)

Side by Side Diff: Source/modules/mediarecorder/MediaRecorder.cpp

Issue 1255873002: MediaRecorder Blink part (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: peter@ comments. Removed BlobEvent, moved MediaRecorder* to Source/modules/mediarecorder Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "config.h"
6 #include "modules/mediarecorder/MediaRecorder.h"
7
8 #include "core/dom/DOMError.h"
9 #include "core/fileapi/Blob.h"
10 #include "modules/EventModules.h"
11 #include "modules/EventTargetModules.h"
12 #include "modules/mediarecorder/MediaRecorderErrorEvent.h"
13 #include "platform/blob/BlobData.h"
14 #include "public/platform/Platform.h"
15 #include "public/platform/WebMediaStream.h"
16
17 namespace blink {
18
19 namespace {
20
21 static String stateToString(MediaRecorder::State state)
22 {
23 switch (state) {
24 case MediaRecorder::State::Inactive:
25 return "inactive";
26 case MediaRecorder::State::Recording:
27 return "recording";
28 case MediaRecorder::State::Paused:
29 return "paused";
30 }
31
32 ASSERT_NOT_REACHED();
33 return String();
34 }
35
36 } // namespace
37
38 MediaRecorder* MediaRecorder::create(ExecutionContext* context, MediaStream* str eam, ExceptionState& exceptionState)
39 {
40 MediaRecorder* recorder = new MediaRecorder(context, stream, String(), excep tionState);
41 recorder->suspendIfNeeded();
42
43 return recorder;
44 }
45
46 MediaRecorder* MediaRecorder::create(ExecutionContext* context, MediaStream* str eam, const String& mimeType, ExceptionState& exceptionState)
47 {
48 MediaRecorder* recorder = new MediaRecorder(context, stream, mimeType, excep tionState);
49 recorder->suspendIfNeeded();
50
51 return recorder;
52 }
53
54 MediaRecorder::MediaRecorder(ExecutionContext* context, MediaStream* stream, con st String& mimeType, ExceptionState& exceptionState)
55 : ActiveDOMObject(context)
56 , m_stream(stream)
57 , m_mimeType(mimeType)
58 , m_stopped(true)
59 , m_ignoreMutedMedia(true)
Peter Beverloo 2015/09/01 17:17:12 We currently don't use this property, and only ref
mcasas 2015/09/02 03:10:17 Done.
60 , m_state(State::Inactive)
61 , m_dispatchScheduledEventRunner(this, &MediaRecorder::dispatchScheduledEven t)
62 {
63 m_recorderHandler = adoptPtr(Platform::current()->createMediaRecorderHandler ());
64
65 // TODO(mcasas): Once http://crbug.com/262211 has landed the Chromium parts,
66 // and more concretetely the createMediaRecorderHandler() implementation,
67 // ASSERT() here for |m_recorderHandler|.
68 if (!m_recorderHandler) {
69 exceptionState.throwDOMException(NotSupportedError, "No MediaRecorder ha ndler can be created.");
70 return;
71 }
72
73 if (!m_recorderHandler->initialize(this, stream->descriptor(), m_mimeType)) {
74 exceptionState.throwDOMException(NotSupportedError, "Failed to initializ e native MediaRecorder.");
Peter Beverloo 2015/09/01 17:17:12 The specification states the following: "If the U
mcasas 2015/09/02 03:10:18 Done.
75 return;
76 }
77 m_stopped = false;
78 }
79
80 String MediaRecorder::state() const
81 {
82 return stateToString(m_state);
83 }
84
85 void MediaRecorder::start(ExceptionState& exceptionState)
86 {
87 if (m_state != State::Inactive) {
88 exceptionState.throwDOMException(InvalidStateError, "The MediaRecorder's state is '" + stateToString(m_state) + "'.");
89 return;
90 }
91 m_state = State::Recording;
92
93 m_recorderHandler->start();
94 }
95
96 void MediaRecorder::start(int timeSlice, ExceptionState& exceptionState)
97 {
98 if (m_state != State::Inactive) {
99 exceptionState.throwDOMException(InvalidStateError, "The MediaRecorder's state is '" + stateToString(m_state) + "'.");
100 return;
101 }
102 m_state = State::Recording;
103
104 m_recorderHandler->start(timeSlice);
105 }
106
107 void MediaRecorder::stop(ExceptionState& exceptionState)
108 {
109 if (m_state == State::Inactive) {
110 exceptionState.throwDOMException(InvalidStateError, "The MediaRecorder's state is '" + stateToString(m_state) + "'.");
111 return;
112 }
113
114 stopRecording();
115 }
116
117 void MediaRecorder::pause(ExceptionState& exceptionState)
118 {
119 if (m_state == State::Inactive) {
120 exceptionState.throwDOMException(InvalidStateError, "The MediaRecorder's state is '" + stateToString(m_state) + "'.");
121 return;
122 }
123 if (m_state == State::Paused)
124 return;
125
126 m_state = State::Paused;
127
128 m_recorderHandler->pause();
129
130 scheduleDispatchEvent(Event::create(EventTypeNames::pause));
131 }
132
133 void MediaRecorder::resume(ExceptionState& exceptionState)
134 {
135 if (m_state == State::Inactive) {
136 exceptionState.throwDOMException(InvalidStateError, "The MediaRecorder's state is '" + stateToString(m_state) + "'.");
137 return;
138 }
139 if (m_state == State::Recording)
140 return;
141
142 m_state = State::Recording;
143
144 m_recorderHandler->resume();
145 }
146
147 void MediaRecorder::requestData(ExceptionState& exceptionState)
148 {
149 if (m_state != State::Recording) {
150 exceptionState.throwDOMException(InvalidStateError, "The MediaRecorder's state is '" + stateToString(m_state) + "'.");
151 return;
152 }
153
154 createBlobEvent(BlobData::create());
155 }
156
157 String MediaRecorder::canRecordMimeType(const String& mimeType)
158 {
159 RawPtr<WebMediaRecorderHandler> handler = Platform::current()->createMediaRe corderHandler();
160 if (!handler)
161 return emptyString();
162
163 // MediaRecorder canRecordMimeType() MUST return 'probably' "if the UA is
164 // confident that mimeType represents a type that it can record" [1], but a
165 // number of reasons could prevent the recording from happening as expected,
166 // so 'maybe' is a better option: "Implementors are encouraged to return
167 // "maybe" unless the type can be confidently established as being supported
168 // or not.". Hence this method returns '' or 'maybe', never 'probably'.
169 // [1] http://w3c.github.io/mediacapture-record/MediaRecorder.html#methods
170 return handler->canSupportMimeType(mimeType) ? "maybe" : emptyString();
171 }
172
173 const AtomicString& MediaRecorder::interfaceName() const
174 {
175 return EventTargetNames::MediaRecorder;
176 }
177
178 ExecutionContext* MediaRecorder::executionContext() const
179 {
180 return ActiveDOMObject::executionContext();
181 }
182
183 void MediaRecorder::suspend()
184 {
185 m_dispatchScheduledEventRunner.suspend();
186 }
187
188 void MediaRecorder::resume()
189 {
190 m_dispatchScheduledEventRunner.resume();
191 }
192
193 void MediaRecorder::stop()
194 {
195 if (m_stopped)
196 return;
197
198 m_stopped = true;
199 m_stream.clear();
200 m_recorderHandler.clear();
201
202 scheduleDispatchEvent(Event::create(EventTypeNames::stop));
203 }
204
205 void MediaRecorder::writeData(const char* data, size_t length, bool lastInSlice)
206 {
207 ASSERT(m_state == State::Recording);
208
209 if (m_stopped) {
210 m_stopped = false;
211 scheduleDispatchEvent(Event::create(EventTypeNames::start));
212 }
213
214 // TODO(mcasas): Use |lastInSlice| to indicate to JS that recording is done.
215
216 OwnPtr<BlobData> blobData = BlobData::create();
217 blobData->appendBytes(data, length);
218 createBlobEvent(blobData.release());
219 }
220
221 void MediaRecorder::failOutOfMemory(const WebString& message)
222 {
223 scheduleDispatchEvent(MediaRecorderErrorEvent::create(
Peter Beverloo 2015/09/01 17:17:12 nit: note that you don't have to wrap the line. I
mcasas 2015/09/02 03:10:17 Acknowledged.
224 EventTypeNames::error, false, false, "OutOfMemory", message));
225
226 if (m_state == State::Recording)
227 stopRecording();
228 }
229
230 void MediaRecorder::failIllegalStreamModification(const WebString& message)
231 {
232 scheduleDispatchEvent(MediaRecorderErrorEvent::create(
233 EventTypeNames::error, false, false, "IllegalStreamModification", messag e));
234
235 if (m_state == State::Recording)
236 stopRecording();
237 }
238
239 void MediaRecorder::failOtherRecordingError(const WebString& message)
240 {
241 scheduleDispatchEvent(MediaRecorderErrorEvent::create(
242 EventTypeNames::error, false, false, "OtherRecordingError", message));
243
244 if (m_state == State::Recording)
245 stopRecording();
246 }
247
248 void MediaRecorder::createBlobEvent(PassOwnPtr<BlobData> blobData)
249 {
250 // TODO(mcasas): Launch a BlobEvent when that class is landed.
251 ASSERT_NOT_REACHED();
252 }
253
254 void MediaRecorder::stopRecording()
255 {
256 ASSERT(m_state != State::Inactive);
257 m_state = State::Inactive;
258
259 m_recorderHandler->stop();
260
261 createBlobEvent(BlobData::create());
262
263 scheduleDispatchEvent(Event::create(EventTypeNames::stop));
264 }
265
266 void MediaRecorder::scheduleDispatchEvent(PassRefPtrWillBeRawPtr<Event> event)
267 {
268 m_scheduledEvents.append(event);
269
270 m_dispatchScheduledEventRunner.runAsync();
271 }
272
273 void MediaRecorder::dispatchScheduledEvent()
274 {
275 WillBeHeapVector<RefPtrWillBeMember<Event>> events;
276 events.swap(m_scheduledEvents);
277
278 WillBeHeapVector<RefPtrWillBeMember<Event>>::iterator it = events.begin();
279 for (; it != events.end(); ++it)
280 dispatchEvent((*it).release());
281
282 events.clear();
283 }
284
285 DEFINE_TRACE(MediaRecorder)
286 {
287 visitor->trace(m_stream);
288 RefCountedGarbageCollectedEventTargetWithInlineData<MediaRecorder>::trace(vi sitor);
289 ActiveDOMObject::trace(visitor);
290 }
291
292 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698