Title: [287613] trunk
Revision
287613
Author
you...@apple.com
Date
2022-01-05 03:26:48 -0800 (Wed, 05 Jan 2022)

Log Message

MediaRecorder should support the bitsPerSecond option
https://bugs.webkit.org/show_bug.cgi?id=234784

Reviewed by Darin Adler.

LayoutTests/imported/w3c:

* web-platform-tests/mediacapture-record/MediaRecorder-bitrate.https-expected.txt:

Source/WebCore:

In case bitsPerSecond is set, we now compute audioBitsPerSecond and videoBitsPerSecond value according to it.
We set audioBitsPerSecond to a tenth of bitsPerSecond and set videoBitsPerSecond to the remaining available bandwidth.
We then use minimum values of 8kbps for audio and 80kbps for video.
As per spec, we compute these values at creation, start and stop times.
We introduce dedicated class members for audio and video bitrates, similarly to the spec defining corresponding slots.

Test: http/wpt/mediarecorder/MediaRecorder-bitrate.html

* Modules/mediarecorder/MediaRecorder.cpp:
* Modules/mediarecorder/MediaRecorder.h:
* platform/mediarecorder/MediaRecorderPrivate.cpp:
* platform/mediarecorder/MediaRecorderPrivate.h:
* platform/mediarecorder/MediaRecorderPrivateAVFImpl.cpp:

LayoutTests:

* http/wpt/mediarecorder/MediaRecorder-bitrate-expected.txt: Added.
* http/wpt/mediarecorder/MediaRecorder-bitrate.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (287612 => 287613)


--- trunk/LayoutTests/ChangeLog	2022-01-05 10:46:30 UTC (rev 287612)
+++ trunk/LayoutTests/ChangeLog	2022-01-05 11:26:48 UTC (rev 287613)
@@ -1,5 +1,15 @@
 2022-01-05  Youenn Fablet  <you...@apple.com>
 
+        MediaRecorder should support the bitsPerSecond option
+        https://bugs.webkit.org/show_bug.cgi?id=234784
+
+        Reviewed by Darin Adler.
+
+        * http/wpt/mediarecorder/MediaRecorder-bitrate-expected.txt: Added.
+        * http/wpt/mediarecorder/MediaRecorder-bitrate.html: Added.
+
+2022-01-05  Youenn Fablet  <you...@apple.com>
+
         Fetch using FormData with file doesn't go through Service Worker
         https://bugs.webkit.org/show_bug.cgi?id=187461
         <rdar://problem/41975544>

Added: trunk/LayoutTests/http/wpt/mediarecorder/MediaRecorder-bitrate-expected.txt (0 => 287613)


--- trunk/LayoutTests/http/wpt/mediarecorder/MediaRecorder-bitrate-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/http/wpt/mediarecorder/MediaRecorder-bitrate-expected.txt	2022-01-05 11:26:48 UTC (rev 287613)
@@ -0,0 +1,5 @@
+
+PASS audio bitrate
+PASS video bitrate
+PASS audio video bitrate
+

Added: trunk/LayoutTests/http/wpt/mediarecorder/MediaRecorder-bitrate.html (0 => 287613)


--- trunk/LayoutTests/http/wpt/mediarecorder/MediaRecorder-bitrate.html	                        (rev 0)
+++ trunk/LayoutTests/http/wpt/mediarecorder/MediaRecorder-bitrate.html	2022-01-05 11:26:48 UTC (rev 287613)
@@ -0,0 +1,57 @@
+<!doctype html>
+<html>
+<head>
+    <title>MediaRecorder bitrate</title>
+    <script src=""
+    <script src=""
+</head>
+<body>
+<script>
+promise_test(async (t) => {
+    const stream = await navigator.mediaDevices.getUserMedia({ audio : true });
+
+    let recorder = new MediaRecorder(stream, { bitsPerSecond : 1000000 });
+    assert_equals(recorder.audioBitsPerSecond, 100000, "test 1");
+
+    recorder = new MediaRecorder(stream, { bitsPerSecond : 10000 });
+    assert_equals(recorder.audioBitsPerSecond, 8000, "test 2");
+
+    recorder = new MediaRecorder(stream, { bitsPerSecond : 1000 });
+    assert_equals(recorder.audioBitsPerSecond, 8000, "test 3");
+}, "audio bitrate");
+
+promise_test(async (t) => {
+    const stream = await navigator.mediaDevices.getUserMedia({ video : true });
+
+    let recorder = new MediaRecorder(stream, { bitsPerSecond : 1000000 });
+    assert_equals(recorder.videoBitsPerSecond, 900000, "test 1");
+
+    recorder = new MediaRecorder(stream, { bitsPerSecond : 100000 });
+    assert_equals(recorder.videoBitsPerSecond, 90000, "test 2");
+
+    recorder = new MediaRecorder(stream, { bitsPerSecond : 10000 });
+    assert_equals(recorder.videoBitsPerSecond, 80000, "test 3");
+}, "video bitrate");
+
+promise_test(async (t) => {
+    const stream = await navigator.mediaDevices.getUserMedia({ audio : true, video : true });
+
+    let recorder = new MediaRecorder(stream, { bitsPerSecond : 1000000 });
+    assert_equals(recorder.audioBitsPerSecond, 100000, "test 1");
+    assert_equals(recorder.videoBitsPerSecond, 900000, "test 2");
+
+    recorder = new MediaRecorder(stream, { bitsPerSecond : 200000 });
+    assert_equals(recorder.audioBitsPerSecond, 20000, "test 3");
+    assert_equals(recorder.videoBitsPerSecond, 180000, "test 4");
+
+    recorder = new MediaRecorder(stream, { bitsPerSecond : 88000 });
+    assert_equals(recorder.audioBitsPerSecond, 8800, "test 5");
+    assert_equals(recorder.videoBitsPerSecond, 80000, "test 6");
+
+    recorder = new MediaRecorder(stream, { bitsPerSecond : 50000 });
+    assert_equals(recorder.audioBitsPerSecond, 8000, "test 7");
+    assert_equals(recorder.videoBitsPerSecond, 80000, "test 8");
+}, "audio video bitrate");
+</script>
+</body>
+</html>

Modified: trunk/LayoutTests/imported/w3c/ChangeLog (287612 => 287613)


--- trunk/LayoutTests/imported/w3c/ChangeLog	2022-01-05 10:46:30 UTC (rev 287612)
+++ trunk/LayoutTests/imported/w3c/ChangeLog	2022-01-05 11:26:48 UTC (rev 287613)
@@ -1,5 +1,14 @@
 2022-01-05  Youenn Fablet  <you...@apple.com>
 
+        MediaRecorder should support the bitsPerSecond option
+        https://bugs.webkit.org/show_bug.cgi?id=234784
+
+        Reviewed by Darin Adler.
+
+        * web-platform-tests/mediacapture-record/MediaRecorder-bitrate.https-expected.txt:
+
+2022-01-05  Youenn Fablet  <you...@apple.com>
+
         Fetch using FormData with file doesn't go through Service Worker
         https://bugs.webkit.org/show_bug.cgi?id=187461
         <rdar://problem/41975544>

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/mediacapture-record/MediaRecorder-bitrate.https-expected.txt (287612 => 287613)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/mediacapture-record/MediaRecorder-bitrate.https-expected.txt	2022-01-05 10:46:30 UTC (rev 287612)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/mediacapture-record/MediaRecorder-bitrate.https-expected.txt	2022-01-05 11:26:48 UTC (rev 287613)
@@ -1,11 +1,11 @@
 
 PASS Passing no bitrate config results in defaults
-FAIL Passing bitsPerSecond:0 results in targets close to 0 assert_approx_equals: expected 0 +/- 100000 but got 10192000
+PASS Passing bitsPerSecond:0 results in targets close to 0
 PASS Passing only audioBitsPerSecond:0 results in 0 for audio, default for video
 PASS Passing only videoBitsPerSecond:0 results in 0 for video, default for audio
-FAIL Passing bitsPerSecond:0 overrides audio/video-specific values assert_approx_equals: expected 0 +/- 100000 but got 1100000
-FAIL Passing bitsPerSecond overrides audio/video zero values assert_not_equals: got disallowed value 0
-FAIL Passing bitsPerSecond sets audio/video bitrate values assert_approx_equals: expected 2000000 +/- 100000 but got 10192000
+PASS Passing bitsPerSecond:0 overrides audio/video-specific values
+PASS Passing bitsPerSecond overrides audio/video zero values
+PASS Passing bitsPerSecond sets audio/video bitrate values
 PASS Passing only audioBitsPerSecond results in default for video
 PASS Passing only videoBitsPerSecond results in default for audio
 PASS Passing videoBitsPerSecond for audio-only stream still results in something for video
@@ -15,6 +15,6 @@
 PASS Selected default track bitrates are not changed by start()
 PASS Passed-in track bitrates are not changed by start()
 PASS Passing bitsPerSecond for audio/video stream does not change track bitrates in start()
-FAIL Passing bitsPerSecond for audio stream sets video track bitrate to 0 in start() assert_approx_equals: expected 500000 +/- 100000 but got 192000
-FAIL Passing bitsPerSecond for video stream sets audio track bitrate to 0 in start() assert_equals: expected 0 but got 192000
+PASS Passing bitsPerSecond for audio stream sets video track bitrate to 0 in start()
+PASS Passing bitsPerSecond for video stream sets audio track bitrate to 0 in start()
 

Modified: trunk/Source/WebCore/ChangeLog (287612 => 287613)


--- trunk/Source/WebCore/ChangeLog	2022-01-05 10:46:30 UTC (rev 287612)
+++ trunk/Source/WebCore/ChangeLog	2022-01-05 11:26:48 UTC (rev 287613)
@@ -1,5 +1,26 @@
 2022-01-05  Youenn Fablet  <you...@apple.com>
 
+        MediaRecorder should support the bitsPerSecond option
+        https://bugs.webkit.org/show_bug.cgi?id=234784
+
+        Reviewed by Darin Adler.
+
+        In case bitsPerSecond is set, we now compute audioBitsPerSecond and videoBitsPerSecond value according to it.
+        We set audioBitsPerSecond to a tenth of bitsPerSecond and set videoBitsPerSecond to the remaining available bandwidth.
+        We then use minimum values of 8kbps for audio and 80kbps for video.
+        As per spec, we compute these values at creation, start and stop times.
+        We introduce dedicated class members for audio and video bitrates, similarly to the spec defining corresponding slots.
+
+        Test: http/wpt/mediarecorder/MediaRecorder-bitrate.html
+
+        * Modules/mediarecorder/MediaRecorder.cpp:
+        * Modules/mediarecorder/MediaRecorder.h:
+        * platform/mediarecorder/MediaRecorderPrivate.cpp:
+        * platform/mediarecorder/MediaRecorderPrivate.h:
+        * platform/mediarecorder/MediaRecorderPrivateAVFImpl.cpp:
+
+2022-01-05  Youenn Fablet  <you...@apple.com>
+
         Fetch using FormData with file doesn't go through Service Worker
         https://bugs.webkit.org/show_bug.cgi?id=187461
         <rdar://problem/41975544>

Modified: trunk/Source/WebCore/Modules/mediarecorder/MediaRecorder.cpp (287612 => 287613)


--- trunk/Source/WebCore/Modules/mediarecorder/MediaRecorder.cpp	2022-01-05 10:46:30 UTC (rev 287612)
+++ trunk/Source/WebCore/Modules/mediarecorder/MediaRecorder.cpp	2022-01-05 11:26:48 UTC (rev 287613)
@@ -103,7 +103,7 @@
     , m_stream(WTFMove(stream))
     , m_timeSliceTimer([this] { requestData(); })
 {
-    MediaRecorderPrivate::updateOptions(m_options);
+    computeInitialBitRates();
 
     m_tracks = WTF::map(m_stream->getTracks(), [] (auto&& track) -> Ref<MediaStreamTrackPrivate> {
         return track->privateTrack();
@@ -154,8 +154,14 @@
     if (state() != RecordingState::Inactive)
         return Exception { InvalidStateError, "The MediaRecorder's state must be inactive in order to start recording"_s };
 
+    updateBitRates();
+
+    Options options;
+    options.audioBitsPerSecond = m_audioBitsPerSecond;
+    options.videoBitsPerSecond = m_videoBitsPerSecond;
+
     ASSERT(!m_private);
-    auto result = createMediaRecorderPrivate(*document(), m_stream->privateStream(), m_options);
+    auto result = createMediaRecorderPrivate(*document(), m_stream->privateStream(), options);
 
     if (result.hasException())
         return result.releaseException();
@@ -207,6 +213,8 @@
     if (state() == RecordingState::Inactive)
         return;
 
+    updateBitRates();
+
     stopRecordingInternal();
     fetchData([this](auto&& buffer, auto& mimeType, auto timeCode) {
         if (!m_isActive)
@@ -393,6 +401,13 @@
     return m_state != RecordingState::Inactive;
 }
 
+void MediaRecorder::computeBitRates(const MediaStreamPrivate* stream)
+{
+    auto bitRates = MediaRecorderPrivate::computeBitRates(m_options, stream);
+    m_audioBitsPerSecond = bitRates.audio;
+    m_videoBitsPerSecond = bitRates.video;
+}
+
 } // namespace WebCore
 
 #endif // ENABLE(MEDIA_STREAM)

Modified: trunk/Source/WebCore/Modules/mediarecorder/MediaRecorder.h (287612 => 287613)


--- trunk/Source/WebCore/Modules/mediarecorder/MediaRecorder.h	2022-01-05 10:46:30 UTC (rev 287612)
+++ trunk/Source/WebCore/Modules/mediarecorder/MediaRecorder.h	2022-01-05 11:26:48 UTC (rev 287613)
@@ -75,8 +75,8 @@
     ExceptionOr<void> pauseRecording();
     ExceptionOr<void> resumeRecording();
 
-    unsigned videoBitsPerSecond() const { return m_options.videoBitsPerSecond.value_or(0); }
-    unsigned audioBitsPerSecond() const { return m_options.audioBitsPerSecond.value_or(0); }
+    unsigned videoBitsPerSecond() const { return m_videoBitsPerSecond; }
+    unsigned audioBitsPerSecond() const { return m_audioBitsPerSecond; }
 
     MediaStream& stream() { return m_stream.get(); }
 
@@ -99,7 +99,7 @@
     const char* activeDOMObjectName() const final;
     bool virtualHasPendingActivity() const final;
     
-        void stopRecordingInternal(CompletionHandler<void()>&& = [] { });
+    void stopRecordingInternal(CompletionHandler<void()>&& = [] { });
     void dispatchError(Exception&&);
 
     enum class TakePrivateRecorder { No, Yes };
@@ -118,6 +118,10 @@
     void trackEnabledChanged(MediaStreamTrackPrivate&) final;
     void trackSettingsChanged(MediaStreamTrackPrivate&) final { };
 
+    void computeInitialBitRates() { computeBitRates(nullptr); }
+    void updateBitRates() { computeBitRates(&m_stream->privateStream()); }
+    void computeBitRates(const MediaStreamPrivate*);
+
     static CreatorFunction m_customCreator;
 
     Options m_options;
@@ -131,6 +135,9 @@
     bool m_isActive { true };
     bool m_isFetchingData { false };
     Deque<FetchDataCallback> m_pendingFetchDataTasks;
+
+    unsigned m_audioBitsPerSecond { 0 };
+    unsigned m_videoBitsPerSecond { 0 };
 };
 
 } // namespace WebCore

Modified: trunk/Source/WebCore/platform/mediarecorder/MediaRecorderPrivate.cpp (287612 => 287613)


--- trunk/Source/WebCore/platform/mediarecorder/MediaRecorderPrivate.cpp	2022-01-05 10:46:30 UTC (rev 287612)
+++ trunk/Source/WebCore/platform/mediarecorder/MediaRecorderPrivate.cpp	2022-01-05 11:26:48 UTC (rev 287613)
@@ -32,6 +32,8 @@
 
 namespace WebCore {
 
+constexpr unsigned SmallAudioBitRate = 8000;
+constexpr unsigned SmallVideoBitRate = 80000;
 constexpr unsigned LargeAudioBitRate = 192000;
 constexpr unsigned LargeVideoBitRate = 10000000;
 
@@ -100,13 +102,26 @@
     resumeRecording(WTFMove(completionHandler));
 }
 
-void MediaRecorderPrivate::updateOptions(MediaRecorderPrivateOptions& options)
+MediaRecorderPrivate::BitRates MediaRecorderPrivate::computeBitRates(const MediaRecorderPrivateOptions& options, const MediaStreamPrivate* stream)
 {
-    // FIXME: Add support for options.bitsPerSecond.
-    if (!options.audioBitsPerSecond)
-        options.audioBitsPerSecond = LargeAudioBitRate;
-    if (!options.videoBitsPerSecond)
-        options.videoBitsPerSecond = LargeVideoBitRate;
+    if (options.bitsPerSecond) {
+        bool hasAudio = stream ? stream->hasAudio() : true;
+        bool hasVideo = stream ? stream->hasVideo() : true;
+        auto totalBitsPerSecond = *options.bitsPerSecond;
+
+        if (hasAudio && hasVideo) {
+            auto audioBitsPerSecond =  std::min(LargeAudioBitRate, std::max(SmallAudioBitRate, totalBitsPerSecond / 10));
+            auto remainingBitsPerSecond = totalBitsPerSecond > audioBitsPerSecond ? (totalBitsPerSecond - audioBitsPerSecond) : 0;
+            return { audioBitsPerSecond, std::max(remainingBitsPerSecond, SmallVideoBitRate) };
+        }
+
+        if (hasAudio)
+            return { std::max(SmallAudioBitRate, totalBitsPerSecond), 0 };
+
+        return { 0, std::max(SmallVideoBitRate, totalBitsPerSecond) };
+    }
+
+    return { options.audioBitsPerSecond.value_or(LargeAudioBitRate), options.videoBitsPerSecond.value_or(LargeVideoBitRate) };
 }
 
 } // namespace WebCore

Modified: trunk/Source/WebCore/platform/mediarecorder/MediaRecorderPrivate.h (287612 => 287613)


--- trunk/Source/WebCore/platform/mediarecorder/MediaRecorderPrivate.h	2022-01-05 10:46:30 UTC (rev 287612)
+++ trunk/Source/WebCore/platform/mediarecorder/MediaRecorderPrivate.h	2022-01-05 11:26:48 UTC (rev 287613)
@@ -73,7 +73,11 @@
     void trackMutedChanged(MediaStreamTrackPrivate& track) { checkTrackState(track); }
     void trackEnabledChanged(MediaStreamTrackPrivate& track) { checkTrackState(track); }
 
-    static void updateOptions(MediaRecorderPrivateOptions&);
+    struct BitRates {
+        unsigned audio;
+        unsigned video;
+    };
+    static BitRates computeBitRates(const MediaRecorderPrivateOptions&, const MediaStreamPrivate* = nullptr);
 
 protected:
     void setAudioSource(RefPtr<RealtimeMediaSource>&&);

Modified: trunk/Source/WebCore/platform/mediarecorder/MediaRecorderPrivateAVFImpl.cpp (287612 => 287613)


--- trunk/Source/WebCore/platform/mediarecorder/MediaRecorderPrivateAVFImpl.cpp	2022-01-05 10:46:30 UTC (rev 287612)
+++ trunk/Source/WebCore/platform/mediarecorder/MediaRecorderPrivateAVFImpl.cpp	2022-01-05 11:26:48 UTC (rev 287613)
@@ -79,7 +79,6 @@
 void MediaRecorderPrivateAVFImpl::startRecording(StartRecordingCallback&& callback)
 {
     // FIMXE: In case of of audio recording, we should wait for the audio compression to start to give back the exact bit rate.
-    // FIXME: Add support to options.bitsPerSecond as well.
     callback(String(m_writer->mimeType()), m_writer->audioBitRate(), m_writer->videoBitRate());
 }
 
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to