Changeset 263511 in webkit
- Timestamp:
- Jun 25, 2020 8:58:41 AM (4 years ago)
- Location:
- trunk
- Files:
-
- 2 added
- 14 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r263510 r263511 1 2020-06-25 Youenn Fablet <youenn@apple.com> 2 3 MediaRecorder stopRecorder() returns empty Blob after first use 4 https://bugs.webkit.org/show_bug.cgi?id=212274 5 <rdar://problem/63601298> 6 7 Reviewed by Eric Carlson. 8 9 * http/wpt/mediarecorder/MediaRecorder-multiple-start-stop-expected.txt: Added. 10 * http/wpt/mediarecorder/MediaRecorder-multiple-start-stop.html: Added. 11 1 12 2020-06-25 Karl Rackler <rackler@apple.com> 2 13 -
trunk/Source/WebCore/ChangeLog
r263509 r263511 1 2020-06-25 Youenn Fablet <youenn@apple.com> 2 3 MediaRecorder stopRecorder() returns empty Blob after first use 4 https://bugs.webkit.org/show_bug.cgi?id=212274 5 <rdar://problem/63601298> 6 7 Reviewed by Eric Carlson. 8 9 Refactor code to create/destroy MediaRecorderPrivate on MediaRecorder start/stop. 10 This allows reusing a MediaRecorder after a stop and restarting with a clean state. 11 12 We introduce MediaRecorderPrivate::startRecording to do the initialization, 13 which allows to fix a potential ref cycle as part of the error callback handling. 14 15 Make some improvements to the platform implementation, in particular add default initialization to all fields. 16 Align the code using AudioConverterRef to what is done in AudioSampleDataSource. 17 Also call VTCompressionSessionInvalidate when destroying the VideoSampleBufferCompressor. 18 19 Test: http/wpt/mediarecorder/MediaRecorder-multiple-start-stop.html 20 21 * Modules/mediarecorder/MediaRecorder.cpp: 22 (WebCore::MediaRecorder::create): 23 (WebCore::MediaRecorder::MediaRecorder): 24 (WebCore::MediaRecorder::startRecording): 25 (WebCore::MediaRecorder::stopRecording): 26 (WebCore::MediaRecorder::requestData): 27 * Modules/mediarecorder/MediaRecorder.h: 28 * platform/mediarecorder/MediaRecorderPrivate.h: 29 (WebCore::MediaRecorderPrivate::startRecording): 30 * platform/mediarecorder/cocoa/AudioSampleBufferCompressor.h: 31 * platform/mediarecorder/cocoa/AudioSampleBufferCompressor.mm: 32 (WebCore::AudioSampleBufferCompressor::~AudioSampleBufferCompressor): 33 (WebCore::AudioSampleBufferCompressor::initAudioConverterForSourceFormatDescription): 34 (WebCore::AudioSampleBufferCompressor::attachPrimingTrimsIfNeeded): 35 (WebCore::AudioSampleBufferCompressor::gradualDecoderRefreshCount): 36 (WebCore::AudioSampleBufferCompressor::sampleBufferWithNumPackets): 37 (WebCore::AudioSampleBufferCompressor::processSampleBuffersUntilLowWaterTime): 38 * platform/mediarecorder/cocoa/MediaRecorderPrivateWriterCocoa.h: 39 * platform/mediarecorder/cocoa/MediaRecorderPrivateWriterCocoa.mm: 40 (WebCore::MediaRecorderPrivateWriter::stopRecording): 41 * platform/mediarecorder/cocoa/VideoSampleBufferCompressor.mm: 42 (WebCore::VideoSampleBufferCompressor::~VideoSampleBufferCompressor): 43 1 44 2020-06-25 Zalan Bujtas <zalan@apple.com> 2 45 -
trunk/Source/WebCore/Modules/mediarecorder/MediaRecorder.cpp
r263422 r263511 52 52 if (!privateInstance) 53 53 return Exception { NotSupportedError, "The MediaRecorder is unsupported on this platform"_s }; 54 auto recorder = adoptRef(*new MediaRecorder(document, WTFMove(stream), WTFMove( privateInstance), WTFMove(options)));54 auto recorder = adoptRef(*new MediaRecorder(document, WTFMove(stream), WTFMove(options))); 55 55 recorder->suspendIfNeeded(); 56 recorder->m_private->setErrorCallback([recorder](auto&& exception) mutable {57 recorder->dispatchError(WTFMove(*exception));58 });59 56 return recorder; 60 57 } … … 83 80 } 84 81 85 MediaRecorder::MediaRecorder(Document& document, Ref<MediaStream>&& stream, std::unique_ptr<MediaRecorderPrivate>&& privateImpl,Options&& option)82 MediaRecorder::MediaRecorder(Document& document, Ref<MediaStream>&& stream, Options&& option) 86 83 : ActiveDOMObject(document) 87 84 , m_options(WTFMove(option)) 88 85 , m_stream(WTFMove(stream)) 89 , m_private(WTFMove(privateImpl))90 86 { 91 87 m_tracks = WTF::map(m_stream->getTracks(), [] (auto&& track) -> Ref<MediaStreamTrackPrivate> { … … 133 129 { 134 130 UNUSED_PARAM(timeslice); 131 if (!m_isActive) 132 return Exception { InvalidStateError, "The MediaRecorder is not active"_s }; 133 135 134 if (state() != RecordingState::Inactive) 136 135 return Exception { InvalidStateError, "The MediaRecorder's state must be inactive in order to start recording"_s }; 137 136 137 ASSERT(!m_private); 138 m_private = createMediaRecorderPrivate(*document(), m_stream->privateStream()); 139 140 if (!m_private) 141 return Exception { NotSupportedError, "The MediaRecorder is unsupported on this platform"_s }; 142 143 m_private->startRecording([this, pendingActivity = makePendingActivity(*this)](auto&& exception) mutable { 144 if (!m_isActive || !exception) 145 return; 146 147 stopRecordingInternal(); 148 dispatchError(WTFMove(*exception)); 149 }); 150 138 151 for (auto& track : m_tracks) 139 152 track->addObserver(*this); … … 147 160 if (state() == RecordingState::Inactive) 148 161 return Exception { InvalidStateError, "The MediaRecorder's state cannot be inactive"_s }; 149 150 queueTaskKeepingObjectAlive(*this, TaskSource::Networking, [this] { 151 if (!m_isActive || state() == RecordingState::Inactive) 152 return; 153 154 stopRecordingInternal(); 155 ASSERT(m_state == RecordingState::Inactive); 156 m_private->fetchData([this, pendingActivity = makePendingActivity(*this)](auto&& buffer, auto& mimeType) { 162 163 stopRecordingInternal(); 164 auto& privateRecorder = *m_private; 165 privateRecorder.fetchData([this, pendingActivity = makePendingActivity(*this), privateRecorder = WTFMove(m_private)](auto&& buffer, auto& mimeType) { 166 queueTaskKeepingObjectAlive(*this, TaskSource::Networking, [this, buffer = WTFMove(buffer), mimeType]() mutable { 157 167 if (!m_isActive) 158 168 return; 159 160 169 dispatchEvent(BlobEvent::create(eventNames().dataavailableEvent, Event::CanBubble::No, Event::IsCancelable::No, buffer ? Blob::create(buffer.releaseNonNull(), mimeType) : Blob::create())); 161 170 162 171 if (!m_isActive) 163 172 return; 164 165 173 dispatchEvent(Event::create(eventNames().stopEvent, Event::CanBubble::No, Event::IsCancelable::No)); 166 174 }); … … 175 183 176 184 m_private->fetchData([this, pendingActivity = makePendingActivity(*this)](auto&& buffer, auto& mimeType) { 177 if (!m_isActive) 178 return; 179 180 dispatchEvent(BlobEvent::create(eventNames().dataavailableEvent, Event::CanBubble::No, Event::IsCancelable::No, buffer ? Blob::create(buffer.releaseNonNull(), mimeType) : Blob::create())); 185 queueTaskKeepingObjectAlive(*this, TaskSource::Networking, [this, buffer = WTFMove(buffer), mimeType]() mutable { 186 if (!m_isActive) 187 return; 188 189 dispatchEvent(BlobEvent::create(eventNames().dataavailableEvent, Event::CanBubble::No, Event::IsCancelable::No, buffer ? Blob::create(buffer.releaseNonNull(), mimeType) : Blob::create())); 190 }); 181 191 }); 182 192 return { }; -
trunk/Source/WebCore/Modules/mediarecorder/MediaRecorder.h
r261553 r263511 76 76 77 77 private: 78 MediaRecorder(Document&, Ref<MediaStream>&&, std::unique_ptr<MediaRecorderPrivate>&&,Options&& = { });78 MediaRecorder(Document&, Ref<MediaStream>&&, Options&& = { }); 79 79 80 80 static std::unique_ptr<MediaRecorderPrivate> createMediaRecorderPrivate(Document&, MediaStreamPrivate&); -
trunk/Source/WebCore/platform/mediarecorder/MediaRecorderPrivate.h
r261553 r263511 61 61 virtual void stopRecording() = 0; 62 62 63 using ErrorCallback = Function<void(Optional<Exception>&&)>;64 v oid setErrorCallback(ErrorCallback&& errorCallback) { m_errorCallback = WTFMove(errorCallback); }63 using ErrorCallback = CompletionHandler<void(Optional<Exception>&&)>; 64 virtual void startRecording(ErrorCallback&& callback) { callback({ }); } 65 65 66 66 protected: 67 67 void setAudioSource(RefPtr<RealtimeMediaSource>&&); 68 68 void setVideoSource(RefPtr<RealtimeMediaSource>&&); 69 70 protected:71 ErrorCallback m_errorCallback;72 69 73 70 private: -
trunk/Source/WebCore/platform/mediarecorder/cocoa/AudioSampleBufferCompressor.h
r263026 r263511 61 61 62 62 dispatch_queue_t m_serialDispatchQueue; 63 CMTime m_lowWaterTime ;63 CMTime m_lowWaterTime { kCMTimeInvalid }; 64 64 65 65 RetainPtr<CMBufferQueueRef> m_outputBufferQueue; … … 67 67 bool m_isEncoding { false }; 68 68 69 RetainPtr<AudioConverterRef> m_converter;69 AudioConverterRef m_converter { nullptr }; 70 70 AudioStreamBasicDescription m_sourceFormat; 71 71 AudioStreamBasicDescription m_destinationFormat; … … 75 75 Vector<AudioStreamPacketDescription> m_destinationPacketDescriptions; 76 76 77 CMTime m_currentNativePresentationTimeStamp ;78 CMTime m_currentOutputPresentationTimeStamp ;79 CMTime m_remainingPrimeDuration ;77 CMTime m_currentNativePresentationTimeStamp { kCMTimeInvalid }; 78 CMTime m_currentOutputPresentationTimeStamp { kCMTimeInvalid }; 79 CMTime m_remainingPrimeDuration { kCMTimeInvalid }; 80 80 81 81 Vector<char> m_sourceBuffer; -
trunk/Source/WebCore/platform/mediarecorder/cocoa/AudioSampleBufferCompressor.mm
r263026 r263511 59 59 { 60 60 dispatch_release(m_serialDispatchQueue); 61 if (m_converter) { 62 AudioConverterDispose(m_converter); 63 m_converter = nullptr; 64 } 61 65 } 62 66 … … 113 117 return false; 114 118 } 115 m_converter = adoptCF(converter);119 m_converter = converter; 116 120 117 121 size_t cookieSize = 0; 118 122 const void *cookie = CMAudioFormatDescriptionGetMagicCookie(formatDescription, &cookieSize); 119 123 if (cookieSize) { 120 if (auto error = AudioConverterSetProperty(m_converter .get(), kAudioConverterDecompressionMagicCookie, (UInt32)cookieSize, cookie)) {124 if (auto error = AudioConverterSetProperty(m_converter, kAudioConverterDecompressionMagicCookie, (UInt32)cookieSize, cookie)) { 121 125 RELEASE_LOG_ERROR(MediaStream, "AudioSampleBufferCompressor setting kAudioConverterDecompressionMagicCookie failed with %d", error); 122 126 return false; … … 125 129 126 130 size = sizeof(m_sourceFormat); 127 if (auto error = AudioConverterGetProperty(m_converter .get(), kAudioConverterCurrentInputStreamDescription, &size, &m_sourceFormat)) {131 if (auto error = AudioConverterGetProperty(m_converter, kAudioConverterCurrentInputStreamDescription, &size, &m_sourceFormat)) { 128 132 RELEASE_LOG_ERROR(MediaStream, "AudioSampleBufferCompressor getting kAudioConverterCurrentInputStreamDescription failed with %d", error); 129 133 return false; … … 136 140 137 141 size = sizeof(m_destinationFormat); 138 if (auto error = AudioConverterGetProperty(m_converter .get(), kAudioConverterCurrentOutputStreamDescription, &size, &m_destinationFormat)) {142 if (auto error = AudioConverterGetProperty(m_converter, kAudioConverterCurrentOutputStreamDescription, &size, &m_destinationFormat)) { 139 143 RELEASE_LOG_ERROR(MediaStream, "AudioSampleBufferCompressor getting kAudioConverterCurrentOutputStreamDescription failed with %d", error); 140 144 return false; … … 150 154 151 155 size = sizeof(outputBitRate); 152 if (auto error = AudioConverterSetProperty(m_converter .get(), kAudioConverterEncodeBitRate, size, &outputBitRate)) {156 if (auto error = AudioConverterSetProperty(m_converter, kAudioConverterEncodeBitRate, size, &outputBitRate)) { 153 157 RELEASE_LOG_ERROR(MediaStream, "AudioSampleBufferCompressor setting kAudioConverterEncodeBitRate failed with %d", error); 154 158 return false; … … 160 164 size = sizeof(m_maxOutputPacketSize); 161 165 162 if (auto error = AudioConverterGetProperty(m_converter .get(), kAudioConverterPropertyMaximumOutputPacketSize, &size, &m_maxOutputPacketSize)) {166 if (auto error = AudioConverterGetProperty(m_converter, kAudioConverterPropertyMaximumOutputPacketSize, &size, &m_maxOutputPacketSize)) { 163 167 RELEASE_LOG_ERROR(MediaStream, "AudioSampleBufferCompressor getting kAudioConverterPropertyMaximumOutputPacketSize failed with %d", error); 164 168 return false; … … 190 194 UInt32 size = sizeof(primeInfo); 191 195 192 if (auto error = AudioConverterGetProperty(m_converter .get(), kAudioConverterPrimeInfo, &size, &primeInfo)) {196 if (auto error = AudioConverterGetProperty(m_converter, kAudioConverterPrimeInfo, &size, &primeInfo)) { 193 197 RELEASE_LOG_ERROR(MediaStream, "AudioSampleBufferCompressor getting kAudioConverterPrimeInfo failed with %d", error); 194 198 return; … … 212 216 UInt32 delaySize = sizeof(uint32_t); 213 217 uint32_t originalDelayMode = 0; 214 if (auto error = AudioConverterGetProperty(m_converter .get(), kAudioCodecPropertyDelayMode, &delaySize, &originalDelayMode)) {218 if (auto error = AudioConverterGetProperty(m_converter, kAudioCodecPropertyDelayMode, &delaySize, &originalDelayMode)) { 215 219 RELEASE_LOG_ERROR(MediaStream, "AudioSampleBufferCompressor getting kAudioCodecPropertyDelayMode failed with %d", error); 216 220 return nil; … … 218 222 219 223 uint32_t optimalDelayMode = kAudioCodecDelayMode_Optimal; 220 if (auto error = AudioConverterSetProperty(m_converter .get(), kAudioCodecPropertyDelayMode, delaySize, &optimalDelayMode)) {224 if (auto error = AudioConverterSetProperty(m_converter, kAudioCodecPropertyDelayMode, delaySize, &optimalDelayMode)) { 221 225 RELEASE_LOG_ERROR(MediaStream, "AudioSampleBufferCompressor setting kAudioCodecPropertyDelayMode failed with %d", error); 222 226 return nil; … … 225 229 UInt32 primeSize = sizeof(AudioCodecPrimeInfo); 226 230 AudioCodecPrimeInfo primeInfo { 0, 0 }; 227 if (auto error = AudioConverterGetProperty(m_converter .get(), kAudioCodecPropertyPrimeInfo, &primeSize, &primeInfo)) {231 if (auto error = AudioConverterGetProperty(m_converter, kAudioCodecPropertyPrimeInfo, &primeSize, &primeInfo)) { 228 232 RELEASE_LOG_ERROR(MediaStream, "AudioSampleBufferCompressor getting kAudioCodecPropertyPrimeInfo failed with %d", error); 229 233 return nil; 230 234 } 231 235 232 if (auto error = AudioConverterSetProperty(m_converter .get(), kAudioCodecPropertyDelayMode, delaySize, &originalDelayMode)) {236 if (auto error = AudioConverterSetProperty(m_converter, kAudioCodecPropertyDelayMode, delaySize, &originalDelayMode)) { 233 237 RELEASE_LOG_ERROR(MediaStream, "AudioSampleBufferCompressor setting kAudioCodecPropertyDelayMode failed with %d", error); 234 238 return nil; … … 243 247 UInt32 cookieSize = 0; 244 248 245 auto error = AudioConverterGetPropertyInfo(m_converter .get(), kAudioConverterCompressionMagicCookie, &cookieSize, NULL);249 auto error = AudioConverterGetPropertyInfo(m_converter, kAudioConverterCompressionMagicCookie, &cookieSize, NULL); 246 250 if ((error == noErr) && !!cookieSize) { 247 251 cookie.resize(cookieSize); 248 252 249 if (auto error = AudioConverterGetProperty(m_converter .get(), kAudioConverterCompressionMagicCookie, &cookieSize, cookie.data())) {253 if (auto error = AudioConverterGetProperty(m_converter, kAudioConverterCompressionMagicCookie, &cookieSize, cookie.data())) { 250 254 RELEASE_LOG_ERROR(MediaStream, "AudioSampleBufferCompressor getting kAudioConverterCompressionMagicCookie failed with %d", error); 251 255 return nil; … … 440 444 UInt32 numOutputPackets = (UInt32)m_destinationBuffer.capacity() / outputPacketSize; 441 445 442 auto error = AudioConverterFillComplexBuffer(m_converter .get(), audioConverterComplexInputDataProc, this, &numOutputPackets, &fillBufferList, m_destinationPacketDescriptions.data());446 auto error = AudioConverterFillComplexBuffer(m_converter, audioConverterComplexInputDataProc, this, &numOutputPackets, &fillBufferList, m_destinationPacketDescriptions.data()); 443 447 if (error) { 444 448 RELEASE_LOG_ERROR(MediaStream, "AudioSampleBufferCompressor AudioConverterFillComplexBuffer failed with %d", error); -
trunk/Source/WebCore/platform/mediarecorder/cocoa/MediaRecorderPrivateWriterCocoa.h
r263026 r263511 115 115 std::unique_ptr<VideoSampleBufferCompressor> m_videoCompressor; 116 116 RetainPtr<AVAssetWriterInput> m_videoAssetWriterInput; 117 CMTime m_lastVideoPresentationTime ;118 CMTime m_lastVideoDecodingTime ;117 CMTime m_lastVideoPresentationTime { kCMTimeInvalid }; 118 CMTime m_lastVideoDecodingTime { kCMTimeInvalid }; 119 119 bool m_hasEncodedVideoSamples { false }; 120 120 -
trunk/Source/WebCore/platform/mediarecorder/cocoa/MediaRecorderPrivateWriterCocoa.mm
r263084 r263511 436 436 // We hop to the main thread since finishing the video compressor might trigger starting the writer asynchronously. 437 437 callOnMainThread([this, weakThis = makeWeakPtr(this)]() mutable { 438 auto whenFinished = [this] { 438 auto whenFinished = [this, weakThis] { 439 if (!weakThis) 440 return; 441 439 442 m_isStopping = false; 440 if (m_fetchDataCompletionHandler) {441 auto buffer = WTFMove(m_data);442 m_fetchDataCompletionHandler(WTFMove(buffer));443 }444 445 443 m_isStopped = false; 446 444 m_hasStartedWriting = false; 447 clear(); 445 446 if (m_writer) 447 m_writer.clear(); 448 if (m_fetchDataCompletionHandler) 449 m_fetchDataCompletionHandler(std::exchange(m_data, nullptr)); 448 450 }; 449 451 … … 462 464 ALLOW_DEPRECATED_DECLARATIONS_END 463 465 464 [m_writer finishWritingWithCompletionHandler:[weakThis = WTFMove(weakThis), whenFinished = WTFMove(whenFinished)]() mutable { 465 callOnMainThread([weakThis = WTFMove(weakThis), whenFinished = WTFMove(whenFinished)]() mutable { 466 if (!weakThis) 467 return; 468 whenFinished(); 469 }); 466 [m_writer finishWritingWithCompletionHandler:[whenFinished = WTFMove(whenFinished)]() mutable { 467 callOnMainThread(WTFMove(whenFinished)); 470 468 }]; 471 469 }); -
trunk/Source/WebCore/platform/mediarecorder/cocoa/VideoSampleBufferCompressor.mm
r263026 r263511 57 57 { 58 58 dispatch_release(m_serialDispatchQueue); 59 if (m_vtSession) { 60 VTCompressionSessionInvalidate(m_vtSession.get()); 61 m_vtSession = nullptr; 62 } 59 63 } 60 64 -
trunk/Source/WebKit/ChangeLog
r263500 r263511 1 2020-06-25 Youenn Fablet <youenn@apple.com> 2 3 MediaRecorder stopRecorder() returns empty Blob after first use 4 https://bugs.webkit.org/show_bug.cgi?id=212274 5 <rdar://problem/63601298> 6 7 Reviewed by Eric Carlson. 8 9 Update implementation to do initialization as part of startRecording. 10 11 * GPUProcess/webrtc/RemoteMediaRecorderManager.cpp: 12 (WebKit::RemoteMediaRecorderManager::releaseRecorder): 13 Remove ASSERT as recorder creation in WebProcess is always ok while creation in GPUProcess may fail and m_recorders may not be populated. 14 * WebProcess/GPU/webrtc/MediaRecorderPrivate.cpp: 15 (WebKit::MediaRecorderPrivate::MediaRecorderPrivate): 16 (WebKit::MediaRecorderPrivate::startRecording): 17 * WebProcess/GPU/webrtc/MediaRecorderPrivate.h: 18 1 19 2020-06-24 James Savage <james.savage@apple.com> 2 20 -
trunk/Source/WebKit/GPUProcess/webrtc/RemoteMediaRecorderManager.cpp
r262708 r263511 65 65 void RemoteMediaRecorderManager::releaseRecorder(MediaRecorderIdentifier identifier) 66 66 { 67 ASSERT(m_recorders.contains(identifier));68 67 m_recorders.remove(identifier); 69 68 } -
trunk/Source/WebKit/WebProcess/GPU/webrtc/MediaRecorderPrivate.cpp
r262708 r263511 46 46 MediaRecorderPrivate::MediaRecorderPrivate(MediaStreamPrivate& stream) 47 47 : m_identifier(MediaRecorderIdentifier::generate()) 48 , m_stream(makeRef(stream)) 48 49 , m_connection(WebProcess::singleton().ensureGPUProcessConnection().connection()) 50 { 51 } 52 53 void MediaRecorderPrivate::startRecording(ErrorCallback&& errorCallback) 49 54 { 50 55 // FIXME: we will need to implement support for multiple audio/video tracks 51 56 // Currently we only choose the first track as the recorded track. 52 57 53 auto selectedTracks = MediaRecorderPrivate::selectTracks( stream);58 auto selectedTracks = MediaRecorderPrivate::selectTracks(m_stream); 54 59 if (selectedTracks.audioTrack) { 55 60 m_ringBuffer = makeUnique<CARingBuffer>(makeUniqueRef<SharedRingBufferStorage>(this)); … … 65 70 } 66 71 67 m_connection->sendWithAsyncReply(Messages::RemoteMediaRecorderManager::CreateRecorder { m_identifier, !!selectedTracks.audioTrack, width, height }, [this, weakThis = makeWeakPtr(this), audioTrack = makeRefPtr(selectedTracks.audioTrack), videoTrack = makeRefPtr(selectedTracks.videoTrack)](auto&& exception) { 68 if (!weakThis) 72 m_connection->sendWithAsyncReply(Messages::RemoteMediaRecorderManager::CreateRecorder { m_identifier, !!selectedTracks.audioTrack, width, height }, [this, weakThis = makeWeakPtr(this), audioTrack = makeRefPtr(selectedTracks.audioTrack), videoTrack = makeRefPtr(selectedTracks.videoTrack), errorCallback = WTFMove(errorCallback)](auto&& exception) mutable { 73 if (!weakThis) { 74 errorCallback({ }); 69 75 return; 70 if (exception) 71 return m_errorCallback(Exception { exception->code, WTFMove(exception->message) }); 76 } 77 if (exception) { 78 errorCallback(Exception { exception->code, WTFMove(exception->message) }); 79 return; 80 } 72 81 if (audioTrack) 73 82 setAudioSource(&audioTrack->source()); 74 83 if (videoTrack) 75 84 setVideoSource(&videoTrack->source()); 85 errorCallback({ }); 76 86 }, 0); 77 87 } -
trunk/Source/WebKit/WebProcess/GPU/webrtc/MediaRecorderPrivate.h
r262708 r263511 59 59 void fetchData(CompletionHandler<void(RefPtr<WebCore::SharedBuffer>&&, const String& mimeType)>&&) final; 60 60 void stopRecording() final; 61 void startRecording(ErrorCallback&&) final; 61 62 void audioSamplesAvailable(const WTF::MediaTime&, const WebCore::PlatformAudioData&, const WebCore::AudioStreamDescription&, size_t) final; 62 63 … … 65 66 66 67 MediaRecorderIdentifier m_identifier; 68 Ref<MediaStreamPrivate> m_stream; 69 Ref<IPC::Connection> m_connection; 67 70 68 Ref<IPC::Connection> m_connection;69 71 String m_recordedAudioTrackID; 70 72 String m_recordedVideoTrackID;
Note: See TracChangeset
for help on using the changeset viewer.