Skip to content

Commit

Permalink
Pausing MediaRecorder still continues to call ondataavailable at ever…
Browse files Browse the repository at this point in the history
…y timeslice event

https://bugs.webkit.org/show_bug.cgi?id=261964
rdar://115979604

Reviewed by Eric Carlson.

Before the patch, we were firing dataavailable events with zero data in case recorder is using timeSlice but is paused.
We are now stopping the timer to stop fetching data when pausing.
When resuming, we restart the timer with the delay left at pause time.

* LayoutTests/http/wpt/mediarecorder/pause-recording-timeSlice-expected.txt: Added.
* LayoutTests/http/wpt/mediarecorder/pause-recording-timeSlice.html: Added.
* Source/WebCore/Modules/mediarecorder/MediaRecorder.cpp:
(WebCore::MediaRecorder::requestData):
(WebCore::MediaRecorder::pauseRecording):
(WebCore::MediaRecorder::resumeRecording):
* Source/WebCore/Modules/mediarecorder/MediaRecorder.h:

Canonical link: https://commits.webkit.org/268433@main
  • Loading branch information
youennf committed Sep 26, 2023
1 parent 92dc762 commit 849a8db
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@

PASS Pausing and resuming the recording should pause dataavailable event

40 changes: 40 additions & 0 deletions LayoutTests/http/wpt/mediarecorder/pause-recording-timeSlice.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
</head>
<body>
<script>
function waitFor(duration)
{
return new Promise((resolve) => setTimeout(resolve, duration));
}

promise_test(async (test) => {
const stream = await navigator.mediaDevices.getUserMedia({ audio: true, video: true });

const recorder = new MediaRecorder(stream);

let counter = 0;
recorder.ondataavailable = (e) => { counter++; }

const startPromise = new Promise(resolve => recorder.onstart = resolve);
recorder.start(100);
await startPromise;

setTimeout(() => recorder.pause(), 50);
setTimeout(() => recorder.resume(), 1550);

await waitFor(500);
const pausedCounter = counter;

await waitFor(500);
assert_equals(counter, pausedCounter);

return new Promise(resolve => recorder.ondataavailable = resolve);
}, "Pausing and resuming the recording should pause dataavailable event");
</script>
</body>
</html>
23 changes: 22 additions & 1 deletion Source/WebCore/Modules/mediarecorder/MediaRecorder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -241,8 +241,17 @@ ExceptionOr<void> MediaRecorder::requestData()

dispatchEvent(createDataAvailableEvent(scriptExecutionContext(), WTFMove(buffer), mimeType, timeCode));

if (m_isActive && m_timeSlice)
switch (state()) {
case RecordingState::Inactive:
break;
case RecordingState::Recording:
ASSERT(m_isActive);
m_timeSliceTimer.startOneShot(Seconds::fromMilliseconds(*m_timeSlice));
break;
case RecordingState::Paused:
m_nextFireInterval = Seconds::fromMilliseconds(*m_timeSlice);
break;
}
}, TakePrivateRecorder::No);
return { };
}
Expand All @@ -256,6 +265,12 @@ ExceptionOr<void> MediaRecorder::pauseRecording()
return { };

m_state = RecordingState::Paused;

if (m_timeSliceTimer.isActive()) {
m_nextFireInterval = m_timeSliceTimer.nextFireInterval();
m_timeSliceTimer.stop();
}

m_private->pause([this, pendingActivity = makePendingActivity(*this)]() {
if (!m_isActive)
return;
Expand All @@ -277,6 +292,12 @@ ExceptionOr<void> MediaRecorder::resumeRecording()
return { };

m_state = RecordingState::Recording;

if (m_nextFireInterval) {
m_timeSliceTimer.startOneShot(*m_nextFireInterval);
m_nextFireInterval = { };
}

m_private->resume([this, pendingActivity = makePendingActivity(*this)]() {
if (!m_isActive)
return;
Expand Down
2 changes: 2 additions & 0 deletions Source/WebCore/Modules/mediarecorder/MediaRecorder.h
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,8 @@ class MediaRecorder final

unsigned m_audioBitsPerSecond { 0 };
unsigned m_videoBitsPerSecond { 0 };

std::optional<Seconds> m_nextFireInterval;
};

} // namespace WebCore
Expand Down

0 comments on commit 849a8db

Please sign in to comment.