Changeset 287613 in webkit


Ignore:
Timestamp:
Jan 5, 2022 3:26:48 AM (7 months ago)
Author:
youenn@apple.com
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.
Location:
trunk
Files:
2 added
9 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r287612 r287613  
     12022-01-05  Youenn Fablet  <youenn@apple.com>
     2
     3        MediaRecorder should support the bitsPerSecond option
     4        https://bugs.webkit.org/show_bug.cgi?id=234784
     5
     6        Reviewed by Darin Adler.
     7
     8        * http/wpt/mediarecorder/MediaRecorder-bitrate-expected.txt: Added.
     9        * http/wpt/mediarecorder/MediaRecorder-bitrate.html: Added.
     10
    1112022-01-05  Youenn Fablet  <youenn@apple.com>
    212
  • trunk/LayoutTests/imported/w3c/ChangeLog

    r287612 r287613  
     12022-01-05  Youenn Fablet  <youenn@apple.com>
     2
     3        MediaRecorder should support the bitsPerSecond option
     4        https://bugs.webkit.org/show_bug.cgi?id=234784
     5
     6        Reviewed by Darin Adler.
     7
     8        * web-platform-tests/mediacapture-record/MediaRecorder-bitrate.https-expected.txt:
     9
    1102022-01-05  Youenn Fablet  <youenn@apple.com>
    211
  • trunk/LayoutTests/imported/w3c/web-platform-tests/mediacapture-record/MediaRecorder-bitrate.https-expected.txt

    r268363 r287613  
    11
    22PASS Passing no bitrate config results in defaults
    3 FAIL Passing bitsPerSecond:0 results in targets close to 0 assert_approx_equals: expected 0 +/- 100000 but got 10192000
     3PASS Passing bitsPerSecond:0 results in targets close to 0
    44PASS Passing only audioBitsPerSecond:0 results in 0 for audio, default for video
    55PASS Passing only videoBitsPerSecond:0 results in 0 for video, default for audio
    6 FAIL Passing bitsPerSecond:0 overrides audio/video-specific values assert_approx_equals: expected 0 +/- 100000 but got 1100000
    7 FAIL Passing bitsPerSecond overrides audio/video zero values assert_not_equals: got disallowed value 0
    8 FAIL Passing bitsPerSecond sets audio/video bitrate values assert_approx_equals: expected 2000000 +/- 100000 but got 10192000
     6PASS Passing bitsPerSecond:0 overrides audio/video-specific values
     7PASS Passing bitsPerSecond overrides audio/video zero values
     8PASS Passing bitsPerSecond sets audio/video bitrate values
    99PASS Passing only audioBitsPerSecond results in default for video
    1010PASS Passing only videoBitsPerSecond results in default for audio
     
    1616PASS Passed-in track bitrates are not changed by start()
    1717PASS Passing bitsPerSecond for audio/video stream does not change track bitrates in start()
    18 FAIL Passing bitsPerSecond for audio stream sets video track bitrate to 0 in start() assert_approx_equals: expected 500000 +/- 100000 but got 192000
    19 FAIL Passing bitsPerSecond for video stream sets audio track bitrate to 0 in start() assert_equals: expected 0 but got 192000
     18PASS Passing bitsPerSecond for audio stream sets video track bitrate to 0 in start()
     19PASS Passing bitsPerSecond for video stream sets audio track bitrate to 0 in start()
    2020
  • trunk/Source/WebCore/ChangeLog

    r287612 r287613  
     12022-01-05  Youenn Fablet  <youenn@apple.com>
     2
     3        MediaRecorder should support the bitsPerSecond option
     4        https://bugs.webkit.org/show_bug.cgi?id=234784
     5
     6        Reviewed by Darin Adler.
     7
     8        In case bitsPerSecond is set, we now compute audioBitsPerSecond and videoBitsPerSecond value according to it.
     9        We set audioBitsPerSecond to a tenth of bitsPerSecond and set videoBitsPerSecond to the remaining available bandwidth.
     10        We then use minimum values of 8kbps for audio and 80kbps for video.
     11        As per spec, we compute these values at creation, start and stop times.
     12        We introduce dedicated class members for audio and video bitrates, similarly to the spec defining corresponding slots.
     13
     14        Test: http/wpt/mediarecorder/MediaRecorder-bitrate.html
     15
     16        * Modules/mediarecorder/MediaRecorder.cpp:
     17        * Modules/mediarecorder/MediaRecorder.h:
     18        * platform/mediarecorder/MediaRecorderPrivate.cpp:
     19        * platform/mediarecorder/MediaRecorderPrivate.h:
     20        * platform/mediarecorder/MediaRecorderPrivateAVFImpl.cpp:
     21
    1222022-01-05  Youenn Fablet  <youenn@apple.com>
    223
  • trunk/Source/WebCore/Modules/mediarecorder/MediaRecorder.cpp

    r287021 r287613  
    104104    , m_timeSliceTimer([this] { requestData(); })
    105105{
    106     MediaRecorderPrivate::updateOptions(m_options);
     106    computeInitialBitRates();
    107107
    108108    m_tracks = WTF::map(m_stream->getTracks(), [] (auto&& track) -> Ref<MediaStreamTrackPrivate> {
     
    155155        return Exception { InvalidStateError, "The MediaRecorder's state must be inactive in order to start recording"_s };
    156156
     157    updateBitRates();
     158
     159    Options options;
     160    options.audioBitsPerSecond = m_audioBitsPerSecond;
     161    options.videoBitsPerSecond = m_videoBitsPerSecond;
     162
    157163    ASSERT(!m_private);
    158     auto result = createMediaRecorderPrivate(*document(), m_stream->privateStream(), m_options);
     164    auto result = createMediaRecorderPrivate(*document(), m_stream->privateStream(), options);
    159165
    160166    if (result.hasException())
     
    208214        return;
    209215
     216    updateBitRates();
     217
    210218    stopRecordingInternal();
    211219    fetchData([this](auto&& buffer, auto& mimeType, auto timeCode) {
     
    394402}
    395403
     404void MediaRecorder::computeBitRates(const MediaStreamPrivate* stream)
     405{
     406    auto bitRates = MediaRecorderPrivate::computeBitRates(m_options, stream);
     407    m_audioBitsPerSecond = bitRates.audio;
     408    m_videoBitsPerSecond = bitRates.video;
     409}
     410
    396411} // namespace WebCore
    397412
  • trunk/Source/WebCore/Modules/mediarecorder/MediaRecorder.h

    r287021 r287613  
    7676    ExceptionOr<void> resumeRecording();
    7777
    78     unsigned videoBitsPerSecond() const { return m_options.videoBitsPerSecond.value_or(0); }
    79     unsigned audioBitsPerSecond() const { return m_options.audioBitsPerSecond.value_or(0); }
     78    unsigned videoBitsPerSecond() const { return m_videoBitsPerSecond; }
     79    unsigned audioBitsPerSecond() const { return m_audioBitsPerSecond; }
    8080
    8181    MediaStream& stream() { return m_stream.get(); }
     
    100100    bool virtualHasPendingActivity() const final;
    101101   
    102         void stopRecordingInternal(CompletionHandler<void()>&& = [] { });
     102    void stopRecordingInternal(CompletionHandler<void()>&& = [] { });
    103103    void dispatchError(Exception&&);
    104104
     
    119119    void trackSettingsChanged(MediaStreamTrackPrivate&) final { };
    120120
     121    void computeInitialBitRates() { computeBitRates(nullptr); }
     122    void updateBitRates() { computeBitRates(&m_stream->privateStream()); }
     123    void computeBitRates(const MediaStreamPrivate*);
     124
    121125    static CreatorFunction m_customCreator;
    122126
     
    132136    bool m_isFetchingData { false };
    133137    Deque<FetchDataCallback> m_pendingFetchDataTasks;
     138
     139    unsigned m_audioBitsPerSecond { 0 };
     140    unsigned m_videoBitsPerSecond { 0 };
    134141};
    135142
  • trunk/Source/WebCore/platform/mediarecorder/MediaRecorderPrivate.cpp

    r272200 r287613  
    3333namespace WebCore {
    3434
     35constexpr unsigned SmallAudioBitRate = 8000;
     36constexpr unsigned SmallVideoBitRate = 80000;
    3537constexpr unsigned LargeAudioBitRate = 192000;
    3638constexpr unsigned LargeVideoBitRate = 10000000;
     
    101103}
    102104
    103 void MediaRecorderPrivate::updateOptions(MediaRecorderPrivateOptions& options)
     105MediaRecorderPrivate::BitRates MediaRecorderPrivate::computeBitRates(const MediaRecorderPrivateOptions& options, const MediaStreamPrivate* stream)
    104106{
    105     // FIXME: Add support for options.bitsPerSecond.
    106     if (!options.audioBitsPerSecond)
    107         options.audioBitsPerSecond = LargeAudioBitRate;
    108     if (!options.videoBitsPerSecond)
    109         options.videoBitsPerSecond = LargeVideoBitRate;
     107    if (options.bitsPerSecond) {
     108        bool hasAudio = stream ? stream->hasAudio() : true;
     109        bool hasVideo = stream ? stream->hasVideo() : true;
     110        auto totalBitsPerSecond = *options.bitsPerSecond;
     111
     112        if (hasAudio && hasVideo) {
     113            auto audioBitsPerSecond =  std::min(LargeAudioBitRate, std::max(SmallAudioBitRate, totalBitsPerSecond / 10));
     114            auto remainingBitsPerSecond = totalBitsPerSecond > audioBitsPerSecond ? (totalBitsPerSecond - audioBitsPerSecond) : 0;
     115            return { audioBitsPerSecond, std::max(remainingBitsPerSecond, SmallVideoBitRate) };
     116        }
     117
     118        if (hasAudio)
     119            return { std::max(SmallAudioBitRate, totalBitsPerSecond), 0 };
     120
     121        return { 0, std::max(SmallVideoBitRate, totalBitsPerSecond) };
     122    }
     123
     124    return { options.audioBitsPerSecond.value_or(LargeAudioBitRate), options.videoBitsPerSecond.value_or(LargeVideoBitRate) };
    110125}
    111126
  • trunk/Source/WebCore/platform/mediarecorder/MediaRecorderPrivate.h

    r287021 r287613  
    7474    void trackEnabledChanged(MediaStreamTrackPrivate& track) { checkTrackState(track); }
    7575
    76     static void updateOptions(MediaRecorderPrivateOptions&);
     76    struct BitRates {
     77        unsigned audio;
     78        unsigned video;
     79    };
     80    static BitRates computeBitRates(const MediaRecorderPrivateOptions&, const MediaStreamPrivate* = nullptr);
    7781
    7882protected:
  • trunk/Source/WebCore/platform/mediarecorder/MediaRecorderPrivateAVFImpl.cpp

    r285984 r287613  
    8080{
    8181    // FIMXE: In case of of audio recording, we should wait for the audio compression to start to give back the exact bit rate.
    82     // FIXME: Add support to options.bitsPerSecond as well.
    8382    callback(String(m_writer->mimeType()), m_writer->audioBitRate(), m_writer->videoBitRate());
    8483}
Note: See TracChangeset for help on using the changeset viewer.