<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[265328] trunk</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/265328">265328</a></dd>
<dt>Author</dt> <dd>youenn@apple.com</dd>
<dt>Date</dt> <dd>2020-08-06 08:25:39 -0700 (Thu, 06 Aug 2020)</dd>
</dl>

<h3>Log Message</h3>
<pre>Add support for MediaRecorder bitrate options
https://bugs.webkit.org/show_bug.cgi?id=214973

Reviewed by Eric Carlson.

Source/WebCore:

Pipe options to MediaRecorderPrivate constructor.
For the actual implementation, pass it down to VideoSampleBufferCompressor and AudioSampleBufferCompressor.
For AudioSampleBufferCompressor, we do not handle well some bit rates, so for now, we limit to specific values.

Tests: http/wpt/mediarecorder/MediaRecorder-audio-bitrate.html
       http/wpt/mediarecorder/MediaRecorder-video-bitrate.html

* Modules/mediarecorder/MediaRecorder.cpp:
(WebCore::MediaRecorder::create):
(WebCore::MediaRecorder::createMediaRecorderPrivate):
(WebCore::MediaRecorder::MediaRecorder):
(WebCore::MediaRecorder::startRecording):
* Modules/mediarecorder/MediaRecorder.h:
* Modules/mediarecorder/MediaRecorderProvider.cpp:
(WebCore::MediaRecorderProvider::createMediaRecorderPrivate):
* Modules/mediarecorder/MediaRecorderProvider.h:
* WebCore.xcodeproj/project.pbxproj:
* loader/EmptyClients.cpp:
* platform/mediarecorder/MediaRecorderPrivate.h:
* platform/mediarecorder/MediaRecorderPrivateAVFImpl.cpp:
(WebCore::MediaRecorderPrivateAVFImpl::create):
* platform/mediarecorder/MediaRecorderPrivateAVFImpl.h:
* platform/mediarecorder/cocoa/AudioSampleBufferCompressor.h:
* platform/mediarecorder/cocoa/AudioSampleBufferCompressor.mm:
(WebCore::AudioSampleBufferCompressor::setBitsPerSecond):
(WebCore::AudioSampleBufferCompressor::outputBitRate const):
(WebCore::AudioSampleBufferCompressor::initAudioConverterForSourceFormatDescription):
Do not exit when not able to set bitrate as we still want to set m_maxOutputPacketSize.
In case of error in setting up the converter, clean it up so that we do not use a partially set up converter.
* platform/mediarecorder/cocoa/MediaRecorderPrivateWriterCocoa.h:
* platform/mediarecorder/cocoa/MediaRecorderPrivateWriterCocoa.mm:
(WebCore::MediaRecorderPrivateWriter::create):
(WebCore::MediaRecorderPrivateWriter::setOptions):
* platform/mediarecorder/cocoa/VideoSampleBufferCompressor.h:
* platform/mediarecorder/cocoa/VideoSampleBufferCompressor.mm:
(WebCore::VideoSampleBufferCompressor::setBitsPerSecond):
(WebCore::setCompressionSessionProperty):
(WebCore::VideoSampleBufferCompressor::initCompressionSession):
* testing/Internals.cpp:
(WebCore::createRecorderMockSource):

Source/WebKit:

Serialize options when creating remote media recorder.

* GPUProcess/webrtc/RemoteMediaRecorder.cpp:
(WebKit::RemoteMediaRecorder::create):
* GPUProcess/webrtc/RemoteMediaRecorder.h:
* GPUProcess/webrtc/RemoteMediaRecorderManager.cpp:
(WebKit::RemoteMediaRecorderManager::createRecorder):
* GPUProcess/webrtc/RemoteMediaRecorderManager.h:
* GPUProcess/webrtc/RemoteMediaRecorderManager.messages.in:
* WebProcess/GPU/webrtc/MediaRecorderPrivate.cpp:
(WebKit::MediaRecorderPrivate::MediaRecorderPrivate):
(WebKit::MediaRecorderPrivate::startRecording):
* WebProcess/GPU/webrtc/MediaRecorderPrivate.h:
* WebProcess/GPU/webrtc/MediaRecorderProvider.cpp:
(WebKit::MediaRecorderProvider::createMediaRecorderPrivate):
* WebProcess/GPU/webrtc/MediaRecorderProvider.h:

LayoutTests:

* http/wpt/mediarecorder/MediaRecorder-audio-bitrate-expected.txt: Added.
* http/wpt/mediarecorder/MediaRecorder-audio-bitrate.html: Added.
* http/wpt/mediarecorder/MediaRecorder-video-bitrate-expected.txt: Added.
* http/wpt/mediarecorder/MediaRecorder-video-bitrate.html: Added.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreModulesmediarecorderMediaRecordercpp">trunk/Source/WebCore/Modules/mediarecorder/MediaRecorder.cpp</a></li>
<li><a href="#trunkSourceWebCoreModulesmediarecorderMediaRecorderh">trunk/Source/WebCore/Modules/mediarecorder/MediaRecorder.h</a></li>
<li><a href="#trunkSourceWebCoreModulesmediarecorderMediaRecorderProvidercpp">trunk/Source/WebCore/Modules/mediarecorder/MediaRecorderProvider.cpp</a></li>
<li><a href="#trunkSourceWebCoreModulesmediarecorderMediaRecorderProviderh">trunk/Source/WebCore/Modules/mediarecorder/MediaRecorderProvider.h</a></li>
<li><a href="#trunkSourceWebCoreWebCorexcodeprojprojectpbxproj">trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj</a></li>
<li><a href="#trunkSourceWebCoreloaderEmptyClientscpp">trunk/Source/WebCore/loader/EmptyClients.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformmediarecorderMediaRecorderPrivateh">trunk/Source/WebCore/platform/mediarecorder/MediaRecorderPrivate.h</a></li>
<li><a href="#trunkSourceWebCoreplatformmediarecorderMediaRecorderPrivateAVFImplcpp">trunk/Source/WebCore/platform/mediarecorder/MediaRecorderPrivateAVFImpl.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformmediarecorderMediaRecorderPrivateAVFImplh">trunk/Source/WebCore/platform/mediarecorder/MediaRecorderPrivateAVFImpl.h</a></li>
<li><a href="#trunkSourceWebCoreplatformmediarecordercocoaAudioSampleBufferCompressorh">trunk/Source/WebCore/platform/mediarecorder/cocoa/AudioSampleBufferCompressor.h</a></li>
<li><a href="#trunkSourceWebCoreplatformmediarecordercocoaAudioSampleBufferCompressormm">trunk/Source/WebCore/platform/mediarecorder/cocoa/AudioSampleBufferCompressor.mm</a></li>
<li><a href="#trunkSourceWebCoreplatformmediarecordercocoaMediaRecorderPrivateWriterCocoah">trunk/Source/WebCore/platform/mediarecorder/cocoa/MediaRecorderPrivateWriterCocoa.h</a></li>
<li><a href="#trunkSourceWebCoreplatformmediarecordercocoaMediaRecorderPrivateWriterCocoamm">trunk/Source/WebCore/platform/mediarecorder/cocoa/MediaRecorderPrivateWriterCocoa.mm</a></li>
<li><a href="#trunkSourceWebCoreplatformmediarecordercocoaVideoSampleBufferCompressorh">trunk/Source/WebCore/platform/mediarecorder/cocoa/VideoSampleBufferCompressor.h</a></li>
<li><a href="#trunkSourceWebCoreplatformmediarecordercocoaVideoSampleBufferCompressormm">trunk/Source/WebCore/platform/mediarecorder/cocoa/VideoSampleBufferCompressor.mm</a></li>
<li><a href="#trunkSourceWebCoretestingInternalscpp">trunk/Source/WebCore/testing/Internals.cpp</a></li>
<li><a href="#trunkSourceWebKitChangeLog">trunk/Source/WebKit/ChangeLog</a></li>
<li><a href="#trunkSourceWebKitGPUProcesswebrtcRemoteMediaRecordercpp">trunk/Source/WebKit/GPUProcess/webrtc/RemoteMediaRecorder.cpp</a></li>
<li><a href="#trunkSourceWebKitGPUProcesswebrtcRemoteMediaRecorderh">trunk/Source/WebKit/GPUProcess/webrtc/RemoteMediaRecorder.h</a></li>
<li><a href="#trunkSourceWebKitGPUProcesswebrtcRemoteMediaRecorderManagercpp">trunk/Source/WebKit/GPUProcess/webrtc/RemoteMediaRecorderManager.cpp</a></li>
<li><a href="#trunkSourceWebKitGPUProcesswebrtcRemoteMediaRecorderManagerh">trunk/Source/WebKit/GPUProcess/webrtc/RemoteMediaRecorderManager.h</a></li>
<li><a href="#trunkSourceWebKitGPUProcesswebrtcRemoteMediaRecorderManagermessagesin">trunk/Source/WebKit/GPUProcess/webrtc/RemoteMediaRecorderManager.messages.in</a></li>
<li><a href="#trunkSourceWebKitWebProcessGPUwebrtcMediaRecorderPrivatecpp">trunk/Source/WebKit/WebProcess/GPU/webrtc/MediaRecorderPrivate.cpp</a></li>
<li><a href="#trunkSourceWebKitWebProcessGPUwebrtcMediaRecorderPrivateh">trunk/Source/WebKit/WebProcess/GPU/webrtc/MediaRecorderPrivate.h</a></li>
<li><a href="#trunkSourceWebKitWebProcessGPUwebrtcMediaRecorderProvidercpp">trunk/Source/WebKit/WebProcess/GPU/webrtc/MediaRecorderProvider.cpp</a></li>
<li><a href="#trunkSourceWebKitWebProcessGPUwebrtcMediaRecorderProviderh">trunk/Source/WebKit/WebProcess/GPU/webrtc/MediaRecorderProvider.h</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkLayoutTestshttpwptmediarecorderMediaRecorderaudiobitrateexpectedtxt">trunk/LayoutTests/http/wpt/mediarecorder/MediaRecorder-audio-bitrate-expected.txt</a></li>
<li><a href="#trunkLayoutTestshttpwptmediarecorderMediaRecorderaudiobitratehtml">trunk/LayoutTests/http/wpt/mediarecorder/MediaRecorder-audio-bitrate.html</a></li>
<li><a href="#trunkLayoutTestshttpwptmediarecorderMediaRecordervideobitrateexpectedtxt">trunk/LayoutTests/http/wpt/mediarecorder/MediaRecorder-video-bitrate-expected.txt</a></li>
<li><a href="#trunkLayoutTestshttpwptmediarecorderMediaRecordervideobitratehtml">trunk/LayoutTests/http/wpt/mediarecorder/MediaRecorder-video-bitrate.html</a></li>
<li><a href="#trunkSourceWebCoreplatformmediarecorderMediaRecorderPrivateOptionsh">trunk/Source/WebCore/platform/mediarecorder/MediaRecorderPrivateOptions.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (265327 => 265328)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog      2020-08-06 14:55:55 UTC (rev 265327)
+++ trunk/LayoutTests/ChangeLog 2020-08-06 15:25:39 UTC (rev 265328)
</span><span class="lines">@@ -1,3 +1,15 @@
</span><ins>+2020-08-06  Youenn Fablet  <youenn@apple.com>
+
+        Add support for MediaRecorder bitrate options
+        https://bugs.webkit.org/show_bug.cgi?id=214973
+
+        Reviewed by Eric Carlson.
+
+        * http/wpt/mediarecorder/MediaRecorder-audio-bitrate-expected.txt: Added.
+        * http/wpt/mediarecorder/MediaRecorder-audio-bitrate.html: Added.
+        * http/wpt/mediarecorder/MediaRecorder-video-bitrate-expected.txt: Added.
+        * http/wpt/mediarecorder/MediaRecorder-video-bitrate.html: Added.
+
</ins><span class="cx"> 2020-08-06  Simon Fraser  <simon.fraser@apple.com>
</span><span class="cx"> 
</span><span class="cx">         Scrolling tree nodes sometimes don't match layer z-order
</span></span></pre></div>
<a id="trunkLayoutTestshttpwptmediarecorderMediaRecorderaudiobitrateexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/http/wpt/mediarecorder/MediaRecorder-audio-bitrate-expected.txt (0 => 265328)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/http/wpt/mediarecorder/MediaRecorder-audio-bitrate-expected.txt                                (rev 0)
+++ trunk/LayoutTests/http/wpt/mediarecorder/MediaRecorder-audio-bitrate-expected.txt   2020-08-06 15:25:39 UTC (rev 265328)
</span><span class="lines">@@ -0,0 +1,3 @@
</span><ins>+
+PASS Various audio bitrates 
+
</ins></span></pre></div>
<a id="trunkLayoutTestshttpwptmediarecorderMediaRecorderaudiobitratehtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/http/wpt/mediarecorder/MediaRecorder-audio-bitrate.html (0 => 265328)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/http/wpt/mediarecorder/MediaRecorder-audio-bitrate.html                                (rev 0)
+++ trunk/LayoutTests/http/wpt/mediarecorder/MediaRecorder-audio-bitrate.html   2020-08-06 15:25:39 UTC (rev 265328)
</span><span class="lines">@@ -0,0 +1,40 @@
</span><ins>+<!doctype html>
+<html>
+<head>
+    <title>MediaRecorder audio bitrate</title>
+    <script src="/resources/testharness.js"></script>
+    <script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<script>
+    async function record(stream, bitRate)
+    {
+        const recorder = new MediaRecorder(stream, { audioBitsPerSecond : bitRate });
+        const promise = new Promise((resolve, reject) => {
+            recorder.ondataavailable = (e) => resolve(e.data);
+            setTimeout(reject, 5000);
+        });
+        recorder.start();
+        setTimeout(() => recorder.stop(), 2500);
+        return promise;
+    }
+
+    promise_test(async (t) => {
+        const stream = await navigator.mediaDevices.getUserMedia({ audio : true });
+        const bitRates = [128000, 192000, 256000];
+        let promises = [];
+        bitRates.forEach(bitRate => {
+            promises.push(record(stream, bitRate));
+        });
+
+        let blobs = [0, 0, 0];
+        promises.forEach(async (promise, index) => {
+            blobs[index] = await promise;
+        });
+        await Promise.all(promises);
+        assert_not_equals(blobs[0].size, 0);
+        assert_greater_than(blobs[2].size, blobs[0].size);
+    }, "Various audio bitrates");
+</script>
+</body>
+</html>
</ins></span></pre></div>
<a id="trunkLayoutTestshttpwptmediarecorderMediaRecordervideobitrateexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/http/wpt/mediarecorder/MediaRecorder-video-bitrate-expected.txt (0 => 265328)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/http/wpt/mediarecorder/MediaRecorder-video-bitrate-expected.txt                                (rev 0)
+++ trunk/LayoutTests/http/wpt/mediarecorder/MediaRecorder-video-bitrate-expected.txt   2020-08-06 15:25:39 UTC (rev 265328)
</span><span class="lines">@@ -0,0 +1,3 @@
</span><ins>+
+PASS Various video bitrates 
+
</ins></span></pre></div>
<a id="trunkLayoutTestshttpwptmediarecorderMediaRecordervideobitratehtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/http/wpt/mediarecorder/MediaRecorder-video-bitrate.html (0 => 265328)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/http/wpt/mediarecorder/MediaRecorder-video-bitrate.html                                (rev 0)
+++ trunk/LayoutTests/http/wpt/mediarecorder/MediaRecorder-video-bitrate.html   2020-08-06 15:25:39 UTC (rev 265328)
</span><span class="lines">@@ -0,0 +1,36 @@
</span><ins>+<!doctype html>
+<html>
+<head>
+    <title>MediaRecorder video bitrate</title>
+    <script src="/resources/testharness.js"></script>
+    <script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<script>
+    async function record(bitRate)
+    {
+        const stream = await navigator.mediaDevices.getUserMedia({ video : { width : 1024 } });
+        const recorder = new MediaRecorder(stream, { videoBitsPerSecond : bitRate });
+        const promise = new Promise((resolve, reject) => {
+            let count = 0;
+            let blobs = [];
+            recorder.ondataavailable = (e) => resolve(e.data);
+            setTimeout(() => reject("datavailable event timed out"), 15000);
+        });
+        recorder.start();
+        setTimeout(() => recorder.stop(), 1000);
+        return promise;
+    }
+
+    promise_test(async (t) => {
+        let blobs = [0, 0];
+        blobs[0] = await record(50000);
+        blobs[1] = await record(5000000);
+
+        // We are taking the second blob since it might be more accurate than the first one.
+        assert_greater_than(blobs[0].size, 0, "blob0");
+        assert_greater_than(blobs[1].size, blobs[0].size, "blob2");
+    }, "Various video bitrates");
+</script>
+</body>
+</html>
</ins></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (265327 => 265328)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog   2020-08-06 14:55:55 UTC (rev 265327)
+++ trunk/Source/WebCore/ChangeLog      2020-08-06 15:25:39 UTC (rev 265328)
</span><span class="lines">@@ -1,3 +1,51 @@
</span><ins>+2020-08-06  Youenn Fablet  <youenn@apple.com>
+
+        Add support for MediaRecorder bitrate options
+        https://bugs.webkit.org/show_bug.cgi?id=214973
+
+        Reviewed by Eric Carlson.
+
+        Pipe options to MediaRecorderPrivate constructor.
+        For the actual implementation, pass it down to VideoSampleBufferCompressor and AudioSampleBufferCompressor.
+        For AudioSampleBufferCompressor, we do not handle well some bit rates, so for now, we limit to specific values.
+
+        Tests: http/wpt/mediarecorder/MediaRecorder-audio-bitrate.html
+               http/wpt/mediarecorder/MediaRecorder-video-bitrate.html
+
+        * Modules/mediarecorder/MediaRecorder.cpp:
+        (WebCore::MediaRecorder::create):
+        (WebCore::MediaRecorder::createMediaRecorderPrivate):
+        (WebCore::MediaRecorder::MediaRecorder):
+        (WebCore::MediaRecorder::startRecording):
+        * Modules/mediarecorder/MediaRecorder.h:
+        * Modules/mediarecorder/MediaRecorderProvider.cpp:
+        (WebCore::MediaRecorderProvider::createMediaRecorderPrivate):
+        * Modules/mediarecorder/MediaRecorderProvider.h:
+        * WebCore.xcodeproj/project.pbxproj:
+        * loader/EmptyClients.cpp:
+        * platform/mediarecorder/MediaRecorderPrivate.h:
+        * platform/mediarecorder/MediaRecorderPrivateAVFImpl.cpp:
+        (WebCore::MediaRecorderPrivateAVFImpl::create):
+        * platform/mediarecorder/MediaRecorderPrivateAVFImpl.h:
+        * platform/mediarecorder/cocoa/AudioSampleBufferCompressor.h:
+        * platform/mediarecorder/cocoa/AudioSampleBufferCompressor.mm:
+        (WebCore::AudioSampleBufferCompressor::setBitsPerSecond):
+        (WebCore::AudioSampleBufferCompressor::outputBitRate const):
+        (WebCore::AudioSampleBufferCompressor::initAudioConverterForSourceFormatDescription):
+        Do not exit when not able to set bitrate as we still want to set m_maxOutputPacketSize.
+        In case of error in setting up the converter, clean it up so that we do not use a partially set up converter.
+        * platform/mediarecorder/cocoa/MediaRecorderPrivateWriterCocoa.h:
+        * platform/mediarecorder/cocoa/MediaRecorderPrivateWriterCocoa.mm:
+        (WebCore::MediaRecorderPrivateWriter::create):
+        (WebCore::MediaRecorderPrivateWriter::setOptions):
+        * platform/mediarecorder/cocoa/VideoSampleBufferCompressor.h:
+        * platform/mediarecorder/cocoa/VideoSampleBufferCompressor.mm:
+        (WebCore::VideoSampleBufferCompressor::setBitsPerSecond):
+        (WebCore::setCompressionSessionProperty):
+        (WebCore::VideoSampleBufferCompressor::initCompressionSession):
+        * testing/Internals.cpp:
+        (WebCore::createRecorderMockSource):
+
</ins><span class="cx"> 2020-08-06  Simon Fraser  <simon.fraser@apple.com>
</span><span class="cx"> 
</span><span class="cx">         Scrolling tree nodes sometimes don't match layer z-order
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesmediarecorderMediaRecordercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/mediarecorder/MediaRecorder.cpp (265327 => 265328)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/mediarecorder/MediaRecorder.cpp     2020-08-06 14:55:55 UTC (rev 265327)
+++ trunk/Source/WebCore/Modules/mediarecorder/MediaRecorder.cpp        2020-08-06 15:25:39 UTC (rev 265328)
</span><span class="lines">@@ -48,9 +48,10 @@
</span><span class="cx"> 
</span><span class="cx"> ExceptionOr<Ref<MediaRecorder>> MediaRecorder::create(Document& document, Ref<MediaStream>&& stream, Options&& options)
</span><span class="cx"> {
</span><del>-    auto privateInstance = MediaRecorder::createMediaRecorderPrivate(document, stream->privateStream());
-    if (!privateInstance)
-        return Exception { NotSupportedError, "The MediaRecorder is unsupported on this platform"_s };
</del><ins>+    auto result = MediaRecorder::createMediaRecorderPrivate(document, stream->privateStream(), options);
+    if (result.hasException())
+        return result.releaseException();
+
</ins><span class="cx">     auto recorder = adoptRef(*new MediaRecorder(document, WTFMove(stream), WTFMove(options)));
</span><span class="cx">     recorder->suspendIfNeeded();
</span><span class="cx">     return recorder;
</span><span class="lines">@@ -61,27 +62,27 @@
</span><span class="cx">     m_customCreator = creator;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-std::unique_ptr<MediaRecorderPrivate> MediaRecorder::createMediaRecorderPrivate(Document& document, MediaStreamPrivate& stream)
</del><ins>+ExceptionOr<std::unique_ptr<MediaRecorderPrivate>> MediaRecorder::createMediaRecorderPrivate(Document& document, MediaStreamPrivate& stream, const Options& options)
</ins><span class="cx"> {
</span><span class="cx">     if (m_customCreator)
</span><del>-        return m_customCreator(stream);
</del><ins>+        return m_customCreator(stream, options);
</ins><span class="cx"> 
</span><span class="cx"> #if PLATFORM(COCOA)
</span><span class="cx">     auto* page = document.page();
</span><span class="cx">     if (!page)
</span><del>-        return nullptr;
</del><ins>+        return Exception { InvalidStateError };
</ins><span class="cx"> 
</span><del>-    return page->mediaRecorderProvider().createMediaRecorderPrivate(stream);
</del><ins>+    return page->mediaRecorderProvider().createMediaRecorderPrivate(stream, options);
</ins><span class="cx"> #else
</span><span class="cx">     UNUSED_PARAM(document);
</span><span class="cx">     UNUSED_PARAM(stream);
</span><del>-    return nullptr;
</del><ins>+    return Exception { NotSupportedError, "The MediaRecorder is unsupported on this platform"_s };
</ins><span class="cx"> #endif
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-MediaRecorder::MediaRecorder(Document& document, Ref<MediaStream>&& stream, Options&& option)
</del><ins>+MediaRecorder::MediaRecorder(Document& document, Ref<MediaStream>&& stream, Options&& options)
</ins><span class="cx">     : ActiveDOMObject(document)
</span><del>-    , m_options(WTFMove(option))
</del><ins>+    , m_options(WTFMove(options))
</ins><span class="cx">     , m_stream(WTFMove(stream))
</span><span class="cx">     , m_timeSliceTimer([this] { requestData(); })
</span><span class="cx"> {
</span><span class="lines">@@ -135,11 +136,13 @@
</span><span class="cx">         return Exception { InvalidStateError, "The MediaRecorder's state must be inactive in order to start recording"_s };
</span><span class="cx"> 
</span><span class="cx">     ASSERT(!m_private);
</span><del>-    m_private = createMediaRecorderPrivate(*document(), m_stream->privateStream());
</del><ins>+    auto result = createMediaRecorderPrivate(*document(), m_stream->privateStream(), m_options);
</ins><span class="cx"> 
</span><del>-    if (!m_private)
-        return Exception { NotSupportedError, "The MediaRecorder is unsupported on this platform"_s };
</del><ins>+    ASSERT(!result.hasException());
+    if (result.hasException())
+        return result.releaseException();
</ins><span class="cx"> 
</span><ins>+    m_private = result.releaseReturnValue();
</ins><span class="cx">     m_private->startRecording([this, pendingActivity = makePendingActivity(*this)](auto&& exception) mutable {
</span><span class="cx">         if (!m_isActive)
</span><span class="cx">             return;
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesmediarecorderMediaRecorderh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/mediarecorder/MediaRecorder.h (265327 => 265328)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/mediarecorder/MediaRecorder.h       2020-08-06 14:55:55 UTC (rev 265327)
+++ trunk/Source/WebCore/Modules/mediarecorder/MediaRecorder.h  2020-08-06 15:25:39 UTC (rev 265328)
</span><span class="lines">@@ -28,6 +28,8 @@
</span><span class="cx"> 
</span><span class="cx"> #include "ActiveDOMObject.h"
</span><span class="cx"> #include "EventTarget.h"
</span><ins>+#include "ExceptionOr.h"
+#include "MediaRecorderPrivateOptions.h"
</ins><span class="cx"> #include "MediaStream.h"
</span><span class="cx"> #include "MediaStreamTrackPrivate.h"
</span><span class="cx"> #include "Timer.h"
</span><span class="lines">@@ -49,18 +51,12 @@
</span><span class="cx"> public:
</span><span class="cx">     enum class RecordingState { Inactive, Recording, Paused };
</span><span class="cx">     
</span><del>-    struct Options {
-        String mimeType;
-        unsigned audioBitsPerSecond;
-        unsigned videoBitsPerSecond;
-        unsigned bitsPerSecond;
-    };
-    
</del><span class="cx">     ~MediaRecorder();
</span><span class="cx">     
</span><ins>+    using Options = MediaRecorderPrivateOptions;
</ins><span class="cx">     static ExceptionOr<Ref<MediaRecorder>> create(Document&, Ref<MediaStream>&&, Options&& = { });
</span><span class="cx">     
</span><del>-    using CreatorFunction = std::unique_ptr<MediaRecorderPrivate>(*)(MediaStreamPrivate&);
</del><ins>+    using CreatorFunction = ExceptionOr<std::unique_ptr<MediaRecorderPrivate>> (*)(MediaStreamPrivate&, const Options&);
</ins><span class="cx"> 
</span><span class="cx">     WEBCORE_EXPORT static void setCustomPrivateRecorderCreator(CreatorFunction);
</span><span class="cx">     
</span><span class="lines">@@ -76,9 +72,9 @@
</span><span class="cx">     MediaStream& stream() { return m_stream.get(); }
</span><span class="cx"> 
</span><span class="cx"> private:
</span><del>-    MediaRecorder(Document&, Ref<MediaStream>&&, Options&& = { });
</del><ins>+    MediaRecorder(Document&, Ref<MediaStream>&&, Options&&);
</ins><span class="cx"> 
</span><del>-    static std::unique_ptr<MediaRecorderPrivate> createMediaRecorderPrivate(Document&, MediaStreamPrivate&);
</del><ins>+    static ExceptionOr<std::unique_ptr<MediaRecorderPrivate>> createMediaRecorderPrivate(Document&, MediaStreamPrivate&, const Options&);
</ins><span class="cx">     
</span><span class="cx">     Document* document() const;
</span><span class="cx"> 
</span><span class="lines">@@ -111,7 +107,7 @@
</span><span class="cx">     void trackEnabledChanged(MediaStreamTrackPrivate&) final { };
</span><span class="cx"> 
</span><span class="cx">     static CreatorFunction m_customCreator;
</span><del>-    
</del><ins>+
</ins><span class="cx">     Options m_options;
</span><span class="cx">     Ref<MediaStream> m_stream;
</span><span class="cx">     std::unique_ptr<MediaRecorderPrivate> m_private;
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesmediarecorderMediaRecorderProvidercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/mediarecorder/MediaRecorderProvider.cpp (265327 => 265328)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/mediarecorder/MediaRecorderProvider.cpp     2020-08-06 14:55:55 UTC (rev 265327)
+++ trunk/Source/WebCore/Modules/mediarecorder/MediaRecorderProvider.cpp        2020-08-06 15:25:39 UTC (rev 265328)
</span><span class="lines">@@ -32,12 +32,13 @@
</span><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><del>-std::unique_ptr<MediaRecorderPrivate> MediaRecorderProvider::createMediaRecorderPrivate(MediaStreamPrivate& stream)
</del><ins>+std::unique_ptr<MediaRecorderPrivate> MediaRecorderProvider::createMediaRecorderPrivate(MediaStreamPrivate& stream, const MediaRecorderPrivateOptions& options)
</ins><span class="cx"> {
</span><span class="cx"> #if HAVE(AVASSETWRITERDELEGATE)
</span><del>-    return MediaRecorderPrivateAVFImpl::create(stream);
</del><ins>+    return MediaRecorderPrivateAVFImpl::create(stream, options);
</ins><span class="cx"> #else
</span><span class="cx">     UNUSED_PARAM(stream);
</span><ins>+    UNUSED_PARAM(options);
</ins><span class="cx">     return nullptr;
</span><span class="cx"> #endif
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesmediarecorderMediaRecorderProviderh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/mediarecorder/MediaRecorderProvider.h (265327 => 265328)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/mediarecorder/MediaRecorderProvider.h       2020-08-06 14:55:55 UTC (rev 265327)
+++ trunk/Source/WebCore/Modules/mediarecorder/MediaRecorderProvider.h  2020-08-06 15:25:39 UTC (rev 265328)
</span><span class="lines">@@ -29,6 +29,7 @@
</span><span class="cx"> 
</span><span class="cx"> class MediaRecorderPrivate;
</span><span class="cx"> class MediaStreamPrivate;
</span><ins>+struct MediaRecorderPrivateOptions;
</ins><span class="cx"> 
</span><span class="cx"> class WEBCORE_EXPORT MediaRecorderProvider {
</span><span class="cx">     WTF_MAKE_FAST_ALLOCATED;
</span><span class="lines">@@ -37,7 +38,7 @@
</span><span class="cx">     virtual ~MediaRecorderProvider() = default;
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(MEDIA_STREAM) && PLATFORM(COCOA)
</span><del>-    virtual std::unique_ptr<MediaRecorderPrivate> createMediaRecorderPrivate(MediaStreamPrivate&);
</del><ins>+    virtual std::unique_ptr<MediaRecorderPrivate> createMediaRecorderPrivate(MediaStreamPrivate&, const MediaRecorderPrivateOptions&);
</ins><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx">     void setUseGPUProcess(bool value) { m_useGPUProcess = value; }
</span></span></pre></div>
<a id="trunkSourceWebCoreWebCorexcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (265327 => 265328)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj   2020-08-06 14:55:55 UTC (rev 265327)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj      2020-08-06 15:25:39 UTC (rev 265328)
</span><span class="lines">@@ -1052,6 +1052,7 @@
</span><span class="cx">          413E00791DB0E4F2002341D2 /* MemoryRelease.h in Headers */ = {isa = PBXBuildFile; fileRef = 413E00781DB0E4DE002341D2 /* MemoryRelease.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">          414460A22412994500814BE7 /* MediaSessionIdentifier.h in Headers */ = {isa = PBXBuildFile; fileRef = 414460A02412994100814BE7 /* MediaSessionIdentifier.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">          414598C223C8D177002B9CC8 /* LocalSampleBufferDisplayLayer.mm in Sources */ = {isa = PBXBuildFile; fileRef = 414598C123C8AD79002B9CC8 /* LocalSampleBufferDisplayLayer.mm */; };
</span><ins>+               414B7FAD24D81CC10033D442 /* MediaRecorderPrivateOptions.h in Headers */ = {isa = PBXBuildFile; fileRef = 414B7FAB24D81C8F0033D442 /* MediaRecorderPrivateOptions.h */; settings = {ATTRIBUTES = (Private, ); }; };
</ins><span class="cx">           414B82051D6DF0E50077EBE3 /* StructuredClone.h in Headers */ = {isa = PBXBuildFile; fileRef = 414B82031D6DF0D90077EBE3 /* StructuredClone.h */; };
</span><span class="cx">          414DEDE71F9FE91E0047C40D /* EmptyFrameLoaderClient.h in Headers */ = {isa = PBXBuildFile; fileRef = 414DEDE51F9FE9150047C40D /* EmptyFrameLoaderClient.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">          415071581685067300C3C7B3 /* SelectorFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 415071561685067300C3C7B3 /* SelectorFilter.h */; };
</span><span class="lines">@@ -7475,6 +7476,7 @@
</span><span class="cx">          414AD40021498D3100521676 /* RTCRtpDecodingParameters.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RTCRtpDecodingParameters.h; sourceTree = "<group>"; };
</span><span class="cx">          414AD40121498D3100521676 /* RTCRtpDecodingParameters.idl */ = {isa = PBXFileReference; lastKnownFileType = text; path = RTCRtpDecodingParameters.idl; sourceTree = "<group>"; };
</span><span class="cx">          414AD40221498D3200521676 /* RTCRtpCodingParameters.idl */ = {isa = PBXFileReference; lastKnownFileType = text; path = RTCRtpCodingParameters.idl; sourceTree = "<group>"; };
</span><ins>+               414B7FAB24D81C8F0033D442 /* MediaRecorderPrivateOptions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MediaRecorderPrivateOptions.h; sourceTree = "<group>"; };
</ins><span class="cx">           414B82021D6DF0D90077EBE3 /* StructuredClone.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StructuredClone.cpp; sourceTree = "<group>"; };
</span><span class="cx">          414B82031D6DF0D90077EBE3 /* StructuredClone.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StructuredClone.h; sourceTree = "<group>"; };
</span><span class="cx">          414DEDE51F9FE9150047C40D /* EmptyFrameLoaderClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EmptyFrameLoaderClient.h; sourceTree = "<group>"; };
</span><span class="lines">@@ -19554,6 +19556,7 @@
</span><span class="cx">                          4D73F944218BC5FA003A3ED6 /* MediaRecorderPrivateAVFImpl.h */,
</span><span class="cx">                          4D9F6B652182532B0092A9C5 /* MediaRecorderPrivateMock.cpp */,
</span><span class="cx">                          4D9F6B642182532B0092A9C5 /* MediaRecorderPrivateMock.h */,
</span><ins>+                               414B7FAB24D81C8F0033D442 /* MediaRecorderPrivateOptions.h */,
</ins><span class="cx">                   );
</span><span class="cx">                  path = mediarecorder;
</span><span class="cx">                  sourceTree = "<group>";
</span><span class="lines">@@ -32568,6 +32571,7 @@
</span><span class="cx">                          4DB7130D216ECB4D0096A4DD /* MediaRecorderErrorEvent.h in Headers */,
</span><span class="cx">                          4D3B5016217E58B700665DB1 /* MediaRecorderPrivate.h in Headers */,
</span><span class="cx">                          4D73F946218BC5FA003A3ED6 /* MediaRecorderPrivateAVFImpl.h in Headers */,
</span><ins>+                               414B7FAD24D81CC10033D442 /* MediaRecorderPrivateOptions.h in Headers */,
</ins><span class="cx">                           4D73F94E218C4A87003A3ED6 /* MediaRecorderPrivateWriterCocoa.h in Headers */,
</span><span class="cx">                          4176E89623C3537B003E83FE /* MediaRecorderProvider.h in Headers */,
</span><span class="cx">                          C90843D01B18E47D00B68564 /* MediaRemoteControls.h in Headers */,
</span></span></pre></div>
<a id="trunkSourceWebCoreloaderEmptyClientscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/loader/EmptyClients.cpp (265327 => 265328)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/loader/EmptyClients.cpp     2020-08-06 14:55:55 UTC (rev 265327)
+++ trunk/Source/WebCore/loader/EmptyClients.cpp        2020-08-06 15:25:39 UTC (rev 265328)
</span><span class="lines">@@ -588,7 +588,7 @@
</span><span class="cx">     EmptyMediaRecorderProvider() = default;
</span><span class="cx"> private:
</span><span class="cx"> #if ENABLE(MEDIA_STREAM) && PLATFORM(COCOA)
</span><del>-    std::unique_ptr<MediaRecorderPrivate> createMediaRecorderPrivate(MediaStreamPrivate&) final { return nullptr; }
</del><ins>+    std::unique_ptr<MediaRecorderPrivate> createMediaRecorderPrivate(MediaStreamPrivate&, const MediaRecorderPrivateOptions&) final { return nullptr; }
</ins><span class="cx"> #endif
</span><span class="cx"> };
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformmediarecorderMediaRecorderPrivateh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/mediarecorder/MediaRecorderPrivate.h (265327 => 265328)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mediarecorder/MediaRecorderPrivate.h       2020-08-06 14:55:55 UTC (rev 265327)
+++ trunk/Source/WebCore/platform/mediarecorder/MediaRecorderPrivate.h  2020-08-06 15:25:39 UTC (rev 265328)
</span><span class="lines">@@ -27,6 +27,7 @@
</span><span class="cx"> #include <wtf/CompletionHandler.h>
</span><span class="cx"> #include <wtf/Forward.h>
</span><span class="cx"> #include "Exception.h"
</span><ins>+#include "MediaRecorderPrivateOptions.h"
</ins><span class="cx"> #include "RealtimeMediaSource.h"
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(MEDIA_STREAM)
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformmediarecorderMediaRecorderPrivateAVFImplcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/mediarecorder/MediaRecorderPrivateAVFImpl.cpp (265327 => 265328)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mediarecorder/MediaRecorderPrivateAVFImpl.cpp      2020-08-06 14:55:55 UTC (rev 265327)
+++ trunk/Source/WebCore/platform/mediarecorder/MediaRecorderPrivateAVFImpl.cpp 2020-08-06 15:25:39 UTC (rev 265328)
</span><span class="lines">@@ -37,7 +37,7 @@
</span><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><del>-std::unique_ptr<MediaRecorderPrivateAVFImpl> MediaRecorderPrivateAVFImpl::create(MediaStreamPrivate& stream)
</del><ins>+std::unique_ptr<MediaRecorderPrivateAVFImpl> MediaRecorderPrivateAVFImpl::create(MediaStreamPrivate& stream, const MediaRecorderPrivateOptions& options)
</ins><span class="cx"> {
</span><span class="cx">     // FIXME: we will need to implement support for multiple audio/video tracks
</span><span class="cx">     // Currently we only choose the first track as the recorded track.
</span><span class="lines">@@ -45,11 +45,11 @@
</span><span class="cx"> 
</span><span class="cx">     auto selectedTracks = MediaRecorderPrivate::selectTracks(stream);
</span><span class="cx"> 
</span><del>-    auto writer = MediaRecorderPrivateWriter::create(!!selectedTracks.audioTrack, !!selectedTracks.videoTrack);
</del><ins>+    auto writer = MediaRecorderPrivateWriter::create(!!selectedTracks.audioTrack, !!selectedTracks.videoTrack, options);
</ins><span class="cx">     if (!writer)
</span><span class="cx">         return nullptr;
</span><span class="cx"> 
</span><del>-    auto recorder = makeUnique<MediaRecorderPrivateAVFImpl>(writer.releaseNonNull());
</del><ins>+    auto recorder = std::unique_ptr<MediaRecorderPrivateAVFImpl>(new MediaRecorderPrivateAVFImpl(writer.releaseNonNull()));
</ins><span class="cx">     if (selectedTracks.audioTrack)
</span><span class="cx">         recorder->setAudioSource(&selectedTracks.audioTrack->source());
</span><span class="cx">     if (selectedTracks.videoTrack)
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformmediarecorderMediaRecorderPrivateAVFImplh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/mediarecorder/MediaRecorderPrivateAVFImpl.h (265327 => 265328)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mediarecorder/MediaRecorderPrivateAVFImpl.h        2020-08-06 14:55:55 UTC (rev 265327)
+++ trunk/Source/WebCore/platform/mediarecorder/MediaRecorderPrivateAVFImpl.h   2020-08-06 15:25:39 UTC (rev 265328)
</span><span class="lines">@@ -37,12 +37,12 @@
</span><span class="cx">     : public MediaRecorderPrivate {
</span><span class="cx">     WTF_MAKE_FAST_ALLOCATED;
</span><span class="cx"> public:
</span><del>-    static std::unique_ptr<MediaRecorderPrivateAVFImpl> create(MediaStreamPrivate&);
</del><ins>+    static std::unique_ptr<MediaRecorderPrivateAVFImpl> create(MediaStreamPrivate&, const MediaRecorderPrivateOptions&);
+    ~MediaRecorderPrivateAVFImpl();
</ins><span class="cx"> 
</span><ins>+private:
</ins><span class="cx">     explicit MediaRecorderPrivateAVFImpl(Ref<MediaRecorderPrivateWriter>&&);
</span><del>-    ~MediaRecorderPrivateAVFImpl();
</del><span class="cx"> 
</span><del>-private:
</del><span class="cx">     // MediaRecorderPrivate
</span><span class="cx">     void videoSampleAvailable(MediaSample&) final;
</span><span class="cx">     void fetchData(FetchDataCallback&&) final;
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformmediarecorderMediaRecorderPrivateOptionsh"></a>
<div class="addfile"><h4>Added: trunk/Source/WebCore/platform/mediarecorder/MediaRecorderPrivateOptions.h (0 => 265328)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mediarecorder/MediaRecorderPrivateOptions.h                                (rev 0)
+++ trunk/Source/WebCore/platform/mediarecorder/MediaRecorderPrivateOptions.h   2020-08-06 15:25:39 UTC (rev 265328)
</span><span class="lines">@@ -0,0 +1,79 @@
</span><ins>+/*
+ * Copyright (C) 2020 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <wtf/Forward.h>
+
+#if ENABLE(MEDIA_STREAM)
+
+namespace WebCore {
+
+struct MediaRecorderPrivateOptions {
+    String mimeType;
+    Optional<unsigned> audioBitsPerSecond;
+    Optional<unsigned> videoBitsPerSecond;
+    Optional<unsigned> bitsPerSecond;
+
+    template<class Encoder> void encode(Encoder&) const;
+    template<class Decoder> static Optional<MediaRecorderPrivateOptions> decode(Decoder&);
+};
+
+template<class Encoder>
+inline void MediaRecorderPrivateOptions::encode(Encoder& encoder) const
+{
+    encoder << mimeType;
+    encoder << audioBitsPerSecond;
+    encoder << videoBitsPerSecond;
+    encoder << bitsPerSecond;
+}
+
+template<class Decoder>
+inline Optional<MediaRecorderPrivateOptions> MediaRecorderPrivateOptions::decode(Decoder& decoder)
+{
+    String mimeType;
+    if (!decoder.decode(mimeType))
+        return WTF::nullopt;
+
+    Optional<Optional<unsigned>> audioBitsPerSecond;
+    decoder >> audioBitsPerSecond;
+    if (!audioBitsPerSecond)
+        return WTF::nullopt;
+
+    Optional<Optional<unsigned>> videoBitsPerSecond;
+    decoder >> videoBitsPerSecond;
+    if (!videoBitsPerSecond)
+        return WTF::nullopt;
+
+    Optional<Optional<unsigned>> bitsPerSecond;
+    decoder >> bitsPerSecond;
+    if (!bitsPerSecond)
+        return WTF::nullopt;
+
+    return MediaRecorderPrivateOptions { WTFMove(mimeType), *audioBitsPerSecond, *videoBitsPerSecond, *bitsPerSecond };
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(MEDIA_STREAM)
</ins></span></pre></div>
<a id="trunkSourceWebCoreplatformmediarecordercocoaAudioSampleBufferCompressorh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/mediarecorder/cocoa/AudioSampleBufferCompressor.h (265327 => 265328)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mediarecorder/cocoa/AudioSampleBufferCompressor.h  2020-08-06 14:55:55 UTC (rev 265327)
+++ trunk/Source/WebCore/platform/mediarecorder/cocoa/AudioSampleBufferCompressor.h     2020-08-06 15:25:39 UTC (rev 265328)
</span><span class="lines">@@ -39,6 +39,7 @@
</span><span class="cx">     static std::unique_ptr<AudioSampleBufferCompressor> create(CMBufferQueueTriggerCallback, void* callbackObject);
</span><span class="cx">     ~AudioSampleBufferCompressor();
</span><span class="cx"> 
</span><ins>+    void setBitsPerSecond(unsigned);
</ins><span class="cx">     void finish();
</span><span class="cx">     void addSampleBuffer(CMSampleBufferRef);
</span><span class="cx">     CMSampleBufferRef getOutputSampleBuffer();
</span><span class="lines">@@ -47,6 +48,7 @@
</span><span class="cx"> private:
</span><span class="cx">     AudioSampleBufferCompressor();
</span><span class="cx">     bool initialize(CMBufferQueueTriggerCallback, void* callbackObject);
</span><ins>+    UInt32 outputBitRate(const AudioStreamBasicDescription&) const;
</ins><span class="cx"> 
</span><span class="cx">     static OSStatus audioConverterComplexInputDataProc(AudioConverterRef, UInt32*, AudioBufferList*, AudioStreamPacketDescription**, void*);
</span><span class="cx"> 
</span><span class="lines">@@ -85,6 +87,7 @@
</span><span class="cx">     size_t m_sampleBlockBufferSize { 0 };
</span><span class="cx">     size_t m_currentOffsetInSampleBlockBuffer { 0 };
</span><span class="cx">     AudioFormatID m_outputCodecType { kAudioFormatMPEG4AAC };
</span><ins>+    Optional<unsigned> m_outputBitRate;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformmediarecordercocoaAudioSampleBufferCompressormm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/mediarecorder/cocoa/AudioSampleBufferCompressor.mm (265327 => 265328)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mediarecorder/cocoa/AudioSampleBufferCompressor.mm 2020-08-06 14:55:55 UTC (rev 265327)
+++ trunk/Source/WebCore/platform/mediarecorder/cocoa/AudioSampleBufferCompressor.mm    2020-08-06 15:25:39 UTC (rev 265328)
</span><span class="lines">@@ -32,6 +32,8 @@
</span><span class="cx"> #include <AudioToolbox/AudioConverter.h>
</span><span class="cx"> #include <AudioToolbox/AudioFormat.h>
</span><span class="cx"> #include <Foundation/Foundation.h>
</span><ins>+#include <algorithm>
+#include <wtf/Scope.h>
</ins><span class="cx"> 
</span><span class="cx"> #import <pal/cf/AudioToolboxSoftLink.h>
</span><span class="cx"> 
</span><span class="lines">@@ -95,6 +97,34 @@
</span><span class="cx">     });
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void AudioSampleBufferCompressor::setBitsPerSecond(unsigned bitRate)
+{
+    // FIXME: we have some issues when setting up some bit rates, only allow some that work for the moment.
+    if (bitRate < 128000) {
+        RELEASE_LOG_INFO(WebRTC, "AudioSampleBufferCompressor::outputBitRate clamped to 128000.");
+        bitRate = 128000;
+    } else if (bitRate > 256000) {
+        RELEASE_LOG_INFO(WebRTC, "AudioSampleBufferCompressor::outputBitRate clamped to 256000.");
+        bitRate = 256000;
+    } else if (bitRate != 128000 && bitRate != 192000 && bitRate != 256000) {
+        RELEASE_LOG_INFO(WebRTC, "AudioSampleBufferCompressor::outputBitRate did not set output bit rate as value is not supported.");
+        return;
+    }
+    m_outputBitRate = bitRate;
+}
+
+UInt32 AudioSampleBufferCompressor::outputBitRate(const AudioStreamBasicDescription& destinationFormat) const
+{
+    if (m_outputBitRate)
+        return *m_outputBitRate;
+
+    if (destinationFormat.mSampleRate >= 44100)
+        return 192000;
+    if (destinationFormat.mSampleRate < 22000)
+        return 32000;
+    return 64000;
+}
+
</ins><span class="cx"> bool AudioSampleBufferCompressor::initAudioConverterForSourceFormatDescription(CMFormatDescriptionRef formatDescription, AudioFormatID outputFormatID)
</span><span class="cx"> {
</span><span class="cx">     const auto *audioFormatListItem = CMAudioFormatDescriptionGetRichestDecodableFormat(formatDescription);
</span><span class="lines">@@ -118,6 +148,11 @@
</span><span class="cx">     }
</span><span class="cx">     m_converter = converter;
</span><span class="cx"> 
</span><ins>+    auto cleanupInCaseOfError = makeScopeExit([&] {
+        AudioConverterDispose(m_converter);
+        m_converter = nullptr;
+    });
+
</ins><span class="cx">     size_t cookieSize = 0;
</span><span class="cx">     const void *cookie = CMAudioFormatDescriptionGetMagicCookie(formatDescription, &cookieSize);
</span><span class="cx">     if (cookieSize) {
</span><span class="lines">@@ -145,18 +180,10 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     if (m_destinationFormat.mFormatID == kAudioFormatMPEG4AAC) {
</span><del>-        // FIXME: Set outputBitRate according MediaRecorderOptions.audioBitsPerSecond.
-        UInt32 outputBitRate = 64000;
-        if (m_destinationFormat.mSampleRate >= 44100)
-            outputBitRate = 192000;
-        else if (m_destinationFormat.mSampleRate < 22000)
-            outputBitRate = 32000;
-
</del><ins>+        auto outputBitRate = this->outputBitRate(m_destinationFormat);
</ins><span class="cx">         size = sizeof(outputBitRate);
</span><del>-        if (auto error = AudioConverterSetProperty(m_converter, kAudioConverterEncodeBitRate, size, &outputBitRate)) {
</del><ins>+        if (auto error = AudioConverterSetProperty(m_converter, kAudioConverterEncodeBitRate, size, &outputBitRate))
</ins><span class="cx">             RELEASE_LOG_ERROR(MediaStream, "AudioSampleBufferCompressor setting kAudioConverterEncodeBitRate failed with %d", error);
</span><del>-            return false;
-        }
</del><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     if (!m_destinationFormat.mBytesPerPacket) {
</span><span class="lines">@@ -169,6 +196,8 @@
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    cleanupInCaseOfError.release();
+
</ins><span class="cx">     auto destinationBufferSize = computeBufferSizeForAudioFormat(m_destinationFormat, m_maxOutputPacketSize, LOW_WATER_TIME_IN_SECONDS);
</span><span class="cx">     if (m_destinationBuffer.size() < destinationBufferSize)
</span><span class="cx">         m_destinationBuffer.resize(destinationBufferSize);
</span><span class="lines">@@ -428,8 +457,10 @@
</span><span class="cx">         m_currentOutputPresentationTimeStamp = CMSampleBufferGetOutputPresentationTimeStamp(buffer);
</span><span class="cx"> 
</span><span class="cx">         auto formatDescription = CMSampleBufferGetFormatDescription(buffer);
</span><del>-        if (!initAudioConverterForSourceFormatDescription(formatDescription, m_outputCodecType))
</del><ins>+        if (!initAudioConverterForSourceFormatDescription(formatDescription, m_outputCodecType)) {
+            // FIXME: Maybe we should error the media recorder if we are not able to get a correct converter.
</ins><span class="cx">             return;
</span><ins>+        }
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     while (CMTIME_IS_INVALID(lowWaterTime) || CMTIME_COMPARE_INLINE(lowWaterTime, <, CMBufferQueueGetDuration(m_inputBufferQueue.get()))) {
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformmediarecordercocoaMediaRecorderPrivateWriterCocoah"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/mediarecorder/cocoa/MediaRecorderPrivateWriterCocoa.h (265327 => 265328)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mediarecorder/cocoa/MediaRecorderPrivateWriterCocoa.h      2020-08-06 14:55:55 UTC (rev 265327)
+++ trunk/Source/WebCore/platform/mediarecorder/cocoa/MediaRecorderPrivateWriterCocoa.h 2020-08-06 15:25:39 UTC (rev 265328)
</span><span class="lines">@@ -59,10 +59,11 @@
</span><span class="cx"> class MediaStreamTrackPrivate;
</span><span class="cx"> class PlatformAudioData;
</span><span class="cx"> class VideoSampleBufferCompressor;
</span><ins>+struct MediaRecorderPrivateOptions;
</ins><span class="cx"> 
</span><span class="cx"> class WEBCORE_EXPORT MediaRecorderPrivateWriter : public ThreadSafeRefCounted<MediaRecorderPrivateWriter, WTF::DestructionThread::Main>, public CanMakeWeakPtr<MediaRecorderPrivateWriter, WeakPtrFactoryInitialization::Eager> {
</span><span class="cx"> public:
</span><del>-    static RefPtr<MediaRecorderPrivateWriter> create(bool hasAudio, bool hasVideo);
</del><ins>+    static RefPtr<MediaRecorderPrivateWriter> create(bool hasAudio, bool hasVideo, const MediaRecorderPrivateOptions&);
</ins><span class="cx">     ~MediaRecorderPrivateWriter();
</span><span class="cx"> 
</span><span class="cx">     void appendVideoSampleBuffer(CMSampleBufferRef);
</span><span class="lines">@@ -78,6 +79,7 @@
</span><span class="cx">     void clear();
</span><span class="cx"> 
</span><span class="cx">     bool initialize();
</span><ins>+    void setOptions(const MediaRecorderPrivateOptions&);
</ins><span class="cx"> 
</span><span class="cx">     static void compressedVideoOutputBufferCallback(void*, CMBufferQueueTriggerToken);
</span><span class="cx">     static void compressedAudioOutputBufferCallback(void*, CMBufferQueueTriggerToken);
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformmediarecordercocoaMediaRecorderPrivateWriterCocoamm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/mediarecorder/cocoa/MediaRecorderPrivateWriterCocoa.mm (265327 => 265328)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mediarecorder/cocoa/MediaRecorderPrivateWriterCocoa.mm     2020-08-06 14:55:55 UTC (rev 265327)
+++ trunk/Source/WebCore/platform/mediarecorder/cocoa/MediaRecorderPrivateWriterCocoa.mm        2020-08-06 15:25:39 UTC (rev 265328)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2018 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2018-2020 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -31,6 +31,7 @@
</span><span class="cx"> #include "AudioSampleBufferCompressor.h"
</span><span class="cx"> #include "AudioStreamDescription.h"
</span><span class="cx"> #include "Logging.h"
</span><ins>+#include "MediaRecorderPrivateOptions.h"
</ins><span class="cx"> #include "MediaStreamTrackPrivate.h"
</span><span class="cx"> #include "VideoSampleBufferCompressor.h"
</span><span class="cx"> #include "WebAudioBufferList.h"
</span><span class="lines">@@ -114,11 +115,12 @@
</span><span class="cx"> 
</span><span class="cx"> using namespace PAL;
</span><span class="cx"> 
</span><del>-RefPtr<MediaRecorderPrivateWriter> MediaRecorderPrivateWriter::create(bool hasAudio, bool hasVideo)
</del><ins>+RefPtr<MediaRecorderPrivateWriter> MediaRecorderPrivateWriter::create(bool hasAudio, bool hasVideo, const MediaRecorderPrivateOptions& options)
</ins><span class="cx"> {
</span><span class="cx">     auto writer = adoptRef(*new MediaRecorderPrivateWriter(hasAudio, hasVideo));
</span><span class="cx">     if (!writer->initialize())
</span><span class="cx">         return nullptr;
</span><ins>+    writer->setOptions(options);
</ins><span class="cx">     return writer;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -176,6 +178,14 @@
</span><span class="cx">     return true;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void MediaRecorderPrivateWriter::setOptions(const MediaRecorderPrivateOptions& options)
+{
+    if (options.audioBitsPerSecond && m_audioCompressor)
+        m_audioCompressor->setBitsPerSecond(*options.audioBitsPerSecond);
+    if (options.videoBitsPerSecond && m_videoCompressor)
+        m_videoCompressor->setBitsPerSecond(*options.videoBitsPerSecond);
+}
+
</ins><span class="cx"> void MediaRecorderPrivateWriter::processNewCompressedVideoSampleBuffers()
</span><span class="cx"> {
</span><span class="cx">     ASSERT(m_hasVideo);
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformmediarecordercocoaVideoSampleBufferCompressorh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/mediarecorder/cocoa/VideoSampleBufferCompressor.h (265327 => 265328)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mediarecorder/cocoa/VideoSampleBufferCompressor.h  2020-08-06 14:55:55 UTC (rev 265327)
+++ trunk/Source/WebCore/platform/mediarecorder/cocoa/VideoSampleBufferCompressor.h     2020-08-06 15:25:39 UTC (rev 265328)
</span><span class="lines">@@ -40,6 +40,7 @@
</span><span class="cx">     static std::unique_ptr<VideoSampleBufferCompressor> create(CMVideoCodecType, CMBufferQueueTriggerCallback, void* callbackObject);
</span><span class="cx">     ~VideoSampleBufferCompressor();
</span><span class="cx"> 
</span><ins>+    void setBitsPerSecond(unsigned);
</ins><span class="cx">     void finish();
</span><span class="cx">     void addSampleBuffer(CMSampleBufferRef);
</span><span class="cx">     CMSampleBufferRef getOutputSampleBuffer();
</span><span class="lines">@@ -64,6 +65,7 @@
</span><span class="cx">     bool m_isEncoding { false };
</span><span class="cx">     float m_maxKeyFrameIntervalDuration { 2.0 };
</span><span class="cx">     unsigned m_expectedFrameRate { 30 };
</span><ins>+    Optional<unsigned> m_outputBitRate;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformmediarecordercocoaVideoSampleBufferCompressormm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/mediarecorder/cocoa/VideoSampleBufferCompressor.mm (265327 => 265328)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mediarecorder/cocoa/VideoSampleBufferCompressor.mm 2020-08-06 14:55:55 UTC (rev 265327)
+++ trunk/Source/WebCore/platform/mediarecorder/cocoa/VideoSampleBufferCompressor.mm    2020-08-06 15:25:39 UTC (rev 265328)
</span><span class="lines">@@ -76,6 +76,11 @@
</span><span class="cx">     return true;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void VideoSampleBufferCompressor::setBitsPerSecond(unsigned bitRate)
+{
+    m_outputBitRate = bitRate;
+}
+
</ins><span class="cx"> void VideoSampleBufferCompressor::finish()
</span><span class="cx"> {
</span><span class="cx">     dispatch_sync(m_serialDispatchQueue, ^{
</span><span class="lines">@@ -101,6 +106,15 @@
</span><span class="cx">     RELEASE_LOG_ERROR_IF(error, MediaStream, "VideoSampleBufferCompressor CMBufferQueueEnqueue failed with %d", error);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+static inline OSStatus setCompressionSessionProperty(VTCompressionSessionRef vtSession, CFStringRef key, uint32_t value)
+{
+    int64_t value64 = value;
+    CFNumberRef cfValue = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt64Type, &value64);
+    OSStatus status = VTSessionSetProperty(vtSession, key, cfValue);
+    CFRelease(cfValue);
+    return status;
+}
+
</ins><span class="cx"> bool VideoSampleBufferCompressor::initCompressionSession(CMVideoFormatDescriptionRef formatDescription)
</span><span class="cx"> {
</span><span class="cx">     CMVideoDimensions dimensions = CMVideoFormatDescriptionGetDimensions(formatDescription);
</span><span class="lines">@@ -120,12 +134,16 @@
</span><span class="cx"> 
</span><span class="cx">     error = VTSessionSetProperty(m_vtSession.get(), kVTCompressionPropertyKey_RealTime, kCFBooleanTrue);
</span><span class="cx">     RELEASE_LOG_ERROR_IF(error, MediaStream, "VideoSampleBufferCompressor VTSessionSetProperty kVTCompressionPropertyKey_RealTime failed with %d", error);
</span><del>-    error = VTSessionSetProperty(m_vtSession.get(), kVTCompressionPropertyKey_MaxKeyFrameIntervalDuration, (__bridge CFTypeRef)@(m_maxKeyFrameIntervalDuration));
</del><ins>+    error = setCompressionSessionProperty(m_vtSession.get(), kVTCompressionPropertyKey_MaxKeyFrameIntervalDuration, m_maxKeyFrameIntervalDuration);
</ins><span class="cx">     RELEASE_LOG_ERROR_IF(error, MediaStream, "VideoSampleBufferCompressor VTSessionSetProperty kVTCompressionPropertyKey_MaxKeyFrameIntervalDuration failed with %d", error);
</span><del>-    error = VTSessionSetProperty(m_vtSession.get(), kVTCompressionPropertyKey_ExpectedFrameRate, (__bridge CFTypeRef)@(m_expectedFrameRate));
</del><ins>+    error = setCompressionSessionProperty(m_vtSession.get(), kVTCompressionPropertyKey_ExpectedFrameRate, m_expectedFrameRate);
</ins><span class="cx">     RELEASE_LOG_ERROR_IF(error, MediaStream, "VideoSampleBufferCompressor VTSessionSetProperty kVTCompressionPropertyKey_ExpectedFrameRate failed with %d", error);
</span><span class="cx"> 
</span><del>-    // FIXME: Set video compression rate.
</del><ins>+    if (m_outputBitRate) {
+        error = setCompressionSessionProperty(m_vtSession.get(), kVTCompressionPropertyKey_AverageBitRate, *m_outputBitRate);
+        RELEASE_LOG_ERROR_IF(error, MediaStream, "VideoSampleBufferCompressor VTSessionSetProperty kVTCompressionPropertyKey_AverageBitRate failed with %d", error);
+    }
+
</ins><span class="cx">     error = VTCompressionSessionPrepareToEncodeFrames(m_vtSession.get());
</span><span class="cx">     RELEASE_LOG_ERROR_IF(error, MediaStream, "VideoSampleBufferCompressor VTCompressionSessionPrepareToEncodeFrames failed with %d", error);
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoretestingInternalscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/testing/Internals.cpp (265327 => 265328)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/testing/Internals.cpp       2020-08-06 14:55:55 UTC (rev 265327)
+++ trunk/Source/WebCore/testing/Internals.cpp  2020-08-06 15:25:39 UTC (rev 265328)
</span><span class="lines">@@ -1691,9 +1691,9 @@
</span><span class="cx">         page->settings().setMediaCaptureRequiresSecureConnection(enabled);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-static std::unique_ptr<MediaRecorderPrivate> createRecorderMockSource(MediaStreamPrivate& stream)
</del><ins>+static ExceptionOr<std::unique_ptr<MediaRecorderPrivate>> createRecorderMockSource(MediaStreamPrivate& stream, const MediaRecorderPrivateOptions&)
</ins><span class="cx"> {
</span><del>-    return std::unique_ptr<MediaRecorderPrivateMock>(new MediaRecorderPrivateMock(stream));
</del><ins>+    return std::unique_ptr<MediaRecorderPrivate>(new MediaRecorderPrivateMock(stream));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void Internals::setCustomPrivateRecorderCreator()
</span><span class="lines">@@ -1700,9 +1700,8 @@
</span><span class="cx"> {
</span><span class="cx">     WebCore::MediaRecorder::setCustomPrivateRecorderCreator(createRecorderMockSource);
</span><span class="cx"> }
</span><ins>+#endif // ENABLE(MEDIA_STREAM)
</ins><span class="cx"> 
</span><del>-#endif
-
</del><span class="cx"> ExceptionOr<Ref<DOMRect>> Internals::absoluteCaretBounds()
</span><span class="cx"> {
</span><span class="cx">     Document* document = contextDocument();
</span></span></pre></div>
<a id="trunkSourceWebKitChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/ChangeLog (265327 => 265328)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/ChangeLog    2020-08-06 14:55:55 UTC (rev 265327)
+++ trunk/Source/WebKit/ChangeLog       2020-08-06 15:25:39 UTC (rev 265328)
</span><span class="lines">@@ -1,3 +1,27 @@
</span><ins>+2020-08-06  Youenn Fablet  <youenn@apple.com>
+
+        Add support for MediaRecorder bitrate options
+        https://bugs.webkit.org/show_bug.cgi?id=214973
+
+        Reviewed by Eric Carlson.
+
+        Serialize options when creating remote media recorder.
+
+        * GPUProcess/webrtc/RemoteMediaRecorder.cpp:
+        (WebKit::RemoteMediaRecorder::create):
+        * GPUProcess/webrtc/RemoteMediaRecorder.h:
+        * GPUProcess/webrtc/RemoteMediaRecorderManager.cpp:
+        (WebKit::RemoteMediaRecorderManager::createRecorder):
+        * GPUProcess/webrtc/RemoteMediaRecorderManager.h:
+        * GPUProcess/webrtc/RemoteMediaRecorderManager.messages.in:
+        * WebProcess/GPU/webrtc/MediaRecorderPrivate.cpp:
+        (WebKit::MediaRecorderPrivate::MediaRecorderPrivate):
+        (WebKit::MediaRecorderPrivate::startRecording):
+        * WebProcess/GPU/webrtc/MediaRecorderPrivate.h:
+        * WebProcess/GPU/webrtc/MediaRecorderProvider.cpp:
+        (WebKit::MediaRecorderProvider::createMediaRecorderPrivate):
+        * WebProcess/GPU/webrtc/MediaRecorderProvider.h:
+
</ins><span class="cx"> 2020-08-06  Adrian Perez de Castro  <aperez@igalia.com>
</span><span class="cx"> 
</span><span class="cx">         [WPE][GTK] Wrong argument order for clone syscall seccomp filter on s390x
</span></span></pre></div>
<a id="trunkSourceWebKitGPUProcesswebrtcRemoteMediaRecordercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/GPUProcess/webrtc/RemoteMediaRecorder.cpp (265327 => 265328)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/GPUProcess/webrtc/RemoteMediaRecorder.cpp    2020-08-06 14:55:55 UTC (rev 265327)
+++ trunk/Source/WebKit/GPUProcess/webrtc/RemoteMediaRecorder.cpp       2020-08-06 15:25:39 UTC (rev 265328)
</span><span class="lines">@@ -38,9 +38,9 @@
</span><span class="cx"> namespace WebKit {
</span><span class="cx"> using namespace WebCore;
</span><span class="cx"> 
</span><del>-std::unique_ptr<RemoteMediaRecorder> RemoteMediaRecorder::create(GPUConnectionToWebProcess& gpuConnectionToWebProcess, MediaRecorderIdentifier identifier, bool recordAudio, bool recordVideo)
</del><ins>+std::unique_ptr<RemoteMediaRecorder> RemoteMediaRecorder::create(GPUConnectionToWebProcess& gpuConnectionToWebProcess, MediaRecorderIdentifier identifier, bool recordAudio, bool recordVideo, const MediaRecorderPrivateOptions& options)
</ins><span class="cx"> {
</span><del>-    auto writer = MediaRecorderPrivateWriter::create(recordAudio, recordVideo);
</del><ins>+    auto writer = MediaRecorderPrivateWriter::create(recordAudio, recordVideo, options);
</ins><span class="cx">     if (!writer)
</span><span class="cx">         return nullptr;
</span><span class="cx">     return std::unique_ptr<RemoteMediaRecorder>(new RemoteMediaRecorder { gpuConnectionToWebProcess, identifier, writer.releaseNonNull(), recordAudio });
</span></span></pre></div>
<a id="trunkSourceWebKitGPUProcesswebrtcRemoteMediaRecorderh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/GPUProcess/webrtc/RemoteMediaRecorder.h (265327 => 265328)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/GPUProcess/webrtc/RemoteMediaRecorder.h      2020-08-06 14:55:55 UTC (rev 265327)
+++ trunk/Source/WebKit/GPUProcess/webrtc/RemoteMediaRecorder.h 2020-08-06 15:25:39 UTC (rev 265328)
</span><span class="lines">@@ -44,6 +44,7 @@
</span><span class="cx"> class CARingBuffer;
</span><span class="cx"> class ImageTransferSessionVT;
</span><span class="cx"> class RemoteVideoSample;
</span><ins>+struct MediaRecorderPrivateOptions;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> namespace WebKit {
</span><span class="lines">@@ -54,7 +55,7 @@
</span><span class="cx"> class RemoteMediaRecorder : private IPC::MessageReceiver {
</span><span class="cx">     WTF_MAKE_FAST_ALLOCATED;
</span><span class="cx"> public:
</span><del>-    static std::unique_ptr<RemoteMediaRecorder> create(GPUConnectionToWebProcess&, MediaRecorderIdentifier, bool recordAudio, bool recordVideo);
</del><ins>+    static std::unique_ptr<RemoteMediaRecorder> create(GPUConnectionToWebProcess&, MediaRecorderIdentifier, bool recordAudio, bool recordVideo, const WebCore::MediaRecorderPrivateOptions&);
</ins><span class="cx">     ~RemoteMediaRecorder();
</span><span class="cx"> 
</span><span class="cx">     void didReceiveMessage(IPC::Connection&, IPC::Decoder&) final;
</span></span></pre></div>
<a id="trunkSourceWebKitGPUProcesswebrtcRemoteMediaRecorderManagercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/GPUProcess/webrtc/RemoteMediaRecorderManager.cpp (265327 => 265328)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/GPUProcess/webrtc/RemoteMediaRecorderManager.cpp     2020-08-06 14:55:55 UTC (rev 265327)
+++ trunk/Source/WebKit/GPUProcess/webrtc/RemoteMediaRecorderManager.cpp        2020-08-06 15:25:39 UTC (rev 265328)
</span><span class="lines">@@ -51,10 +51,10 @@
</span><span class="cx">         recorder->didReceiveMessage(connection, decoder);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void RemoteMediaRecorderManager::createRecorder(MediaRecorderIdentifier identifier, bool recordAudio, bool recordVideo, CompletionHandler<void(Optional<ExceptionData>&&)>&& completionHandler)
</del><ins>+void RemoteMediaRecorderManager::createRecorder(MediaRecorderIdentifier identifier, bool recordAudio, bool recordVideo, const MediaRecorderPrivateOptions& options, CompletionHandler<void(Optional<ExceptionData>&&)>&& completionHandler)
</ins><span class="cx"> {
</span><span class="cx">     ASSERT(!m_recorders.contains(identifier));
</span><del>-    auto recorder = RemoteMediaRecorder::create(m_gpuConnectionToWebProcess, identifier, recordAudio, recordVideo);
</del><ins>+    auto recorder = RemoteMediaRecorder::create(m_gpuConnectionToWebProcess, identifier, recordAudio, recordVideo, options);
</ins><span class="cx">     if (!recorder)
</span><span class="cx">         return completionHandler(ExceptionData { NotSupportedError, "Unable to create a recorder with the provided stream"_s });
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebKitGPUProcesswebrtcRemoteMediaRecorderManagerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/GPUProcess/webrtc/RemoteMediaRecorderManager.h (265327 => 265328)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/GPUProcess/webrtc/RemoteMediaRecorderManager.h       2020-08-06 14:55:55 UTC (rev 265327)
+++ trunk/Source/WebKit/GPUProcess/webrtc/RemoteMediaRecorderManager.h  2020-08-06 15:25:39 UTC (rev 265328)
</span><span class="lines">@@ -41,6 +41,7 @@
</span><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span><span class="cx"> struct ExceptionData;
</span><ins>+struct MediaRecorderPrivateOptions;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> namespace WebKit {
</span><span class="lines">@@ -60,7 +61,7 @@
</span><span class="cx"> private:
</span><span class="cx">     // IPC::MessageReceiver
</span><span class="cx">     void didReceiveMessage(IPC::Connection&, IPC::Decoder&) final;
</span><del>-    void createRecorder(MediaRecorderIdentifier, bool recordAudio, bool recordVideo, CompletionHandler<void(Optional<WebCore::ExceptionData>&&)>&&);
</del><ins>+    void createRecorder(MediaRecorderIdentifier, bool recordAudio, bool recordVideo, const WebCore::MediaRecorderPrivateOptions&, CompletionHandler<void(Optional<WebCore::ExceptionData>&&)>&&);
</ins><span class="cx">     void releaseRecorder(MediaRecorderIdentifier);
</span><span class="cx"> 
</span><span class="cx">     GPUConnectionToWebProcess& m_gpuConnectionToWebProcess;
</span></span></pre></div>
<a id="trunkSourceWebKitGPUProcesswebrtcRemoteMediaRecorderManagermessagesin"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/GPUProcess/webrtc/RemoteMediaRecorderManager.messages.in (265327 => 265328)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/GPUProcess/webrtc/RemoteMediaRecorderManager.messages.in     2020-08-06 14:55:55 UTC (rev 265327)
+++ trunk/Source/WebKit/GPUProcess/webrtc/RemoteMediaRecorderManager.messages.in        2020-08-06 15:25:39 UTC (rev 265328)
</span><span class="lines">@@ -24,7 +24,7 @@
</span><span class="cx"> #if PLATFORM(COCOA) && ENABLE(GPU_PROCESS) && ENABLE(MEDIA_STREAM) && HAVE(AVASSETWRITERDELEGATE)
</span><span class="cx"> 
</span><span class="cx"> messages -> RemoteMediaRecorderManager NotRefCounted {
</span><del>-    CreateRecorder(WebKit::MediaRecorderIdentifier id, bool hasAudio, bool hasVideo) -> (Optional<WebCore::ExceptionData> creationError) Async
</del><ins>+    CreateRecorder(WebKit::MediaRecorderIdentifier id, bool hasAudio, bool hasVideo, struct WebCore::MediaRecorderPrivateOptions options) -> (Optional<WebCore::ExceptionData> creationError) Async
</ins><span class="cx">     ReleaseRecorder(WebKit::MediaRecorderIdentifier id)
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebKitWebProcessGPUwebrtcMediaRecorderPrivatecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/WebProcess/GPU/webrtc/MediaRecorderPrivate.cpp (265327 => 265328)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/WebProcess/GPU/webrtc/MediaRecorderPrivate.cpp       2020-08-06 14:55:55 UTC (rev 265327)
+++ trunk/Source/WebKit/WebProcess/GPU/webrtc/MediaRecorderPrivate.cpp  2020-08-06 15:25:39 UTC (rev 265328)
</span><span class="lines">@@ -43,10 +43,11 @@
</span><span class="cx"> namespace WebKit {
</span><span class="cx"> using namespace WebCore;
</span><span class="cx"> 
</span><del>-MediaRecorderPrivate::MediaRecorderPrivate(MediaStreamPrivate& stream)
</del><ins>+MediaRecorderPrivate::MediaRecorderPrivate(MediaStreamPrivate& stream, const MediaRecorderPrivateOptions& options)
</ins><span class="cx">     : m_identifier(MediaRecorderIdentifier::generate())
</span><span class="cx">     , m_stream(makeRef(stream))
</span><span class="cx">     , m_connection(WebProcess::singleton().ensureGPUProcessConnection().connection())
</span><ins>+    , m_options(options)
</ins><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -59,7 +60,7 @@
</span><span class="cx">     if (selectedTracks.audioTrack)
</span><span class="cx">         m_ringBuffer = makeUnique<CARingBuffer>(makeUniqueRef<SharedRingBufferStorage>(this));
</span><span class="cx"> 
</span><del>-    m_connection->sendWithAsyncReply(Messages::RemoteMediaRecorderManager::CreateRecorder { m_identifier, !!selectedTracks.audioTrack, !!selectedTracks.videoTrack }, [this, weakThis = makeWeakPtr(this), audioTrack = makeRefPtr(selectedTracks.audioTrack), videoTrack = makeRefPtr(selectedTracks.videoTrack), errorCallback = WTFMove(errorCallback)](auto&& exception) mutable {
</del><ins>+    m_connection->sendWithAsyncReply(Messages::RemoteMediaRecorderManager::CreateRecorder { m_identifier, !!selectedTracks.audioTrack, !!selectedTracks.videoTrack, m_options }, [this, weakThis = makeWeakPtr(this), audioTrack = makeRefPtr(selectedTracks.audioTrack), videoTrack = makeRefPtr(selectedTracks.videoTrack), errorCallback = WTFMove(errorCallback)](auto&& exception) mutable {
</ins><span class="cx">         if (!weakThis) {
</span><span class="cx">             errorCallback({ });
</span><span class="cx">             return;
</span></span></pre></div>
<a id="trunkSourceWebKitWebProcessGPUwebrtcMediaRecorderPrivateh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/WebProcess/GPU/webrtc/MediaRecorderPrivate.h (265327 => 265328)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/WebProcess/GPU/webrtc/MediaRecorderPrivate.h 2020-08-06 14:55:55 UTC (rev 265327)
+++ trunk/Source/WebKit/WebProcess/GPU/webrtc/MediaRecorderPrivate.h    2020-08-06 15:25:39 UTC (rev 265328)
</span><span class="lines">@@ -50,7 +50,7 @@
</span><span class="cx">     , public CanMakeWeakPtr<MediaRecorderPrivate> {
</span><span class="cx">     WTF_MAKE_FAST_ALLOCATED;
</span><span class="cx"> public:
</span><del>-    explicit MediaRecorderPrivate(WebCore::MediaStreamPrivate&);
</del><ins>+    MediaRecorderPrivate(WebCore::MediaStreamPrivate&, const WebCore::MediaRecorderPrivateOptions&);
</ins><span class="cx">     ~MediaRecorderPrivate();
</span><span class="cx"> 
</span><span class="cx"> private:
</span><span class="lines">@@ -71,6 +71,7 @@
</span><span class="cx">     std::unique_ptr<WebCore::CARingBuffer> m_ringBuffer;
</span><span class="cx">     WebCore::CAAudioStreamDescription m_description { };
</span><span class="cx">     int64_t m_numberOfFrames { 0 };
</span><ins>+    WebCore::MediaRecorderPrivateOptions m_options;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceWebKitWebProcessGPUwebrtcMediaRecorderProvidercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/WebProcess/GPU/webrtc/MediaRecorderProvider.cpp (265327 => 265328)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/WebProcess/GPU/webrtc/MediaRecorderProvider.cpp      2020-08-06 14:55:55 UTC (rev 265327)
+++ trunk/Source/WebKit/WebProcess/GPU/webrtc/MediaRecorderProvider.cpp 2020-08-06 15:25:39 UTC (rev 265328)
</span><span class="lines">@@ -34,13 +34,13 @@
</span><span class="cx"> namespace WebKit {
</span><span class="cx"> using namespace WebCore;
</span><span class="cx"> 
</span><del>-std::unique_ptr<WebCore::MediaRecorderPrivate> MediaRecorderProvider::createMediaRecorderPrivate(MediaStreamPrivate& stream)
</del><ins>+std::unique_ptr<WebCore::MediaRecorderPrivate> MediaRecorderProvider::createMediaRecorderPrivate(MediaStreamPrivate& stream, const MediaRecorderPrivateOptions& options)
</ins><span class="cx"> {
</span><span class="cx"> #if ENABLE(GPU_PROCESS) && HAVE(AVASSETWRITERDELEGATE)
</span><span class="cx">     if (m_useGPUProcess)
</span><del>-        return makeUnique<MediaRecorderPrivate>(stream);
</del><ins>+        return makeUnique<MediaRecorderPrivate>(stream, options);
</ins><span class="cx"> #endif
</span><del>-    return WebCore::MediaRecorderProvider::createMediaRecorderPrivate(stream);
</del><ins>+    return WebCore::MediaRecorderProvider::createMediaRecorderPrivate(stream, options);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceWebKitWebProcessGPUwebrtcMediaRecorderProviderh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/WebProcess/GPU/webrtc/MediaRecorderProvider.h (265327 => 265328)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/WebProcess/GPU/webrtc/MediaRecorderProvider.h        2020-08-06 14:55:55 UTC (rev 265327)
+++ trunk/Source/WebKit/WebProcess/GPU/webrtc/MediaRecorderProvider.h   2020-08-06 15:25:39 UTC (rev 265328)
</span><span class="lines">@@ -35,7 +35,7 @@
</span><span class="cx"> 
</span><span class="cx"> private:
</span><span class="cx"> #if ENABLE(MEDIA_STREAM) && PLATFORM(COCOA)
</span><del>-    std::unique_ptr<WebCore::MediaRecorderPrivate> createMediaRecorderPrivate(WebCore::MediaStreamPrivate&) final;
</del><ins>+    std::unique_ptr<WebCore::MediaRecorderPrivate> createMediaRecorderPrivate(WebCore::MediaStreamPrivate&, const WebCore::MediaRecorderPrivateOptions&) final;
</ins><span class="cx"> #endif
</span><span class="cx"> };
</span><span class="cx"> 
</span></span></pre>
</div>
</div>

</body>
</html>