Diff
Modified: branches/safari-610-branch/LayoutTests/ChangeLog (268105 => 268106)
--- branches/safari-610-branch/LayoutTests/ChangeLog 2020-10-07 01:02:55 UTC (rev 268105)
+++ branches/safari-610-branch/LayoutTests/ChangeLog 2020-10-07 01:02:59 UTC (rev 268106)
@@ -1,5 +1,61 @@
2020-10-06 Alan Coon <[email protected]>
+ Cherry-pick r267987. rdar://problem/70025699
+
+ MediaRecorder should respect enabled and muted tracks
+ https://bugs.webkit.org/show_bug.cgi?id=217312
+
+ Reviewed by Eric Carlson.
+
+ Source/WebCore:
+
+ If track is muted, replace it by either silence (audio buffer filled with zeros) or black frames.
+ MediaRecorderPrivate will keep track of whether the selected track should be muted.
+ It is then the responsibility of the specialization to do the appropriate processing.
+
+ Test: http/wpt/mediarecorder/mute-tracks.html
+
+ * Modules/mediarecorder/MediaRecorder.cpp:
+ (WebCore::MediaRecorder::trackMutedChanged):
+ (WebCore::MediaRecorder::trackEnabledChanged):
+ * Modules/mediarecorder/MediaRecorder.h:
+ * platform/audio/cocoa/WebAudioBufferList.cpp:
+ (WebCore::WebAudioBufferList::zeroFlatBuffer):
+ * platform/audio/cocoa/WebAudioBufferList.h:
+ * platform/mediarecorder/MediaRecorderPrivate.cpp:
+ (WebCore::MediaRecorderPrivate::selectTracks):
+ (WebCore::MediaRecorderPrivate::checkTrackState):
+ * platform/mediarecorder/MediaRecorderPrivate.h:
+ (WebCore::MediaRecorderPrivate::trackMutedChanged):
+ (WebCore::MediaRecorderPrivate::trackEnabledChanged):
+ (WebCore::MediaRecorderPrivate::shouldMuteAudio const):
+ (WebCore::MediaRecorderPrivate::shouldMuteVideo const):
+ * platform/mediarecorder/MediaRecorderPrivateAVFImpl.cpp:
+ (WebCore::MediaRecorderPrivateAVFImpl::create):
+ (WebCore::MediaRecorderPrivateAVFImpl::videoSampleAvailable):
+ (WebCore::MediaRecorderPrivateAVFImpl::audioSamplesAvailable):
+ * platform/mediarecorder/MediaRecorderPrivateAVFImpl.h:
+
+ LayoutTests:
+
+ * http/wpt/mediarecorder/mute-tracks-expected.txt: Added.
+ * http/wpt/mediarecorder/mute-tracks.html: Added.
+
+
+ git-svn-id: https://svn.webkit.org/repository/webkit/trunk@267987 268f45cc-cd09-0410-ab3c-d52691b4dbfc
+
+ 2020-10-05 Youenn Fablet <[email protected]>
+
+ MediaRecorder should respect enabled and muted tracks
+ https://bugs.webkit.org/show_bug.cgi?id=217312
+
+ Reviewed by Eric Carlson.
+
+ * http/wpt/mediarecorder/mute-tracks-expected.txt: Added.
+ * http/wpt/mediarecorder/mute-tracks.html: Added.
+
+2020-10-06 Alan Coon <[email protected]>
+
Cherry-pick r267870. rdar://problem/70025703
Add AVAssetWriter SPI header
Added: branches/safari-610-branch/LayoutTests/http/wpt/mediarecorder/mute-tracks-expected.txt (0 => 268106)
--- branches/safari-610-branch/LayoutTests/http/wpt/mediarecorder/mute-tracks-expected.txt (rev 0)
+++ branches/safari-610-branch/LayoutTests/http/wpt/mediarecorder/mute-tracks-expected.txt 2020-10-07 01:02:59 UTC (rev 268106)
@@ -0,0 +1,6 @@
+
+
+PASS Recording a muted audio track should prodcue silence
+PASS Muting an audio track should record silence
+PASS Muting a video track should produce black frames
+
Added: branches/safari-610-branch/LayoutTests/http/wpt/mediarecorder/mute-tracks.html (0 => 268106)
--- branches/safari-610-branch/LayoutTests/http/wpt/mediarecorder/mute-tracks.html (rev 0)
+++ branches/safari-610-branch/LayoutTests/http/wpt/mediarecorder/mute-tracks.html 2020-10-07 01:02:59 UTC (rev 268106)
@@ -0,0 +1,211 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>A recorded muted audio track should produce silence</title>
+ <script src=""
+ <script src=""
+</head>
+<body>
+ <video id="video1" controls></video>
+ <video id="video2" controls></video>
+ <video id="video3" controls></video>
+ <canvas id="canvas3" width="320" height="240"></canvas>
+ <script>
+if (window.internals)
+ window.internals.setUseGPUProcessForWebRTC(false);
+
+function analyseAudio(streamOrVideo, duration, context)
+{
+ return new Promise((resolve, reject) => {
+ var sourceNode = streamOrVideo instanceof MediaStream ? context.createMediaStreamSource(streamOrVideo) : context.createMediaElementSource(streamOrVideo);
+
+ var analyser = context.createAnalyser();
+ var gain = context.createGain();
+
+ var results = { heardHum: false, heardBip: false, heardBop: false, heardNoise: false };
+
+ analyser.fftSize = 2048;
+ analyser.smoothingTimeConstant = 0;
+ analyser.minDecibels = -100;
+ analyser.maxDecibels = 0;
+ gain.gain.value = 0;
+
+ sourceNode.connect(analyser);
+ analyser.connect(gain);
+ gain.connect(context.destination);
+
+ function analyse() {
+ var freqDomain = new Uint8Array(analyser.frequencyBinCount);
+ analyser.getByteFrequencyData(freqDomain);
+
+ var hasFrequency = expectedFrequency => {
+ var bin = Math.floor(expectedFrequency * analyser.fftSize / context.sampleRate);
+ return bin < freqDomain.length && freqDomain[bin] >= 150;
+ };
+
+ if (!results.heardHum)
+ results.heardHum = hasFrequency(150);
+
+ if (!results.heardBip)
+ results.heardBip = hasFrequency(1500);
+
+ if (!results.heardBop)
+ results.heardBop = hasFrequency(500);
+
+ if (!results.heardNoise)
+ results.heardNoise = hasFrequency(3000);
+
+ if (results.heardHum && results.heardBip && results.heardBop && results.heardNoise)
+ done();
+ };
+
+ function done() {
+ clearTimeout(timeout);
+ clearInterval(interval);
+
+ resolve(results);
+ }
+
+ var timeout = setTimeout(done, 3 * duration);
+ var interval = setInterval(analyse, duration / 30);
+ analyse();
+ });
+}
+
+function waitFor(duration)
+{
+ return new Promise((resolve) => setTimeout(resolve, duration));
+}
+
+async function doHumAnalysis(streamOrVideo, expected)
+{
+ var context = new AudioContext();
+ for (var cptr = 0; cptr < 20; cptr++) {
+ var results = await analyseAudio(streamOrVideo, 200, context);
+ if (results.heardHum === expected)
+ return true;
+ await waitFor(50);
+ }
+ await context.close();
+ return false;
+}
+
+function isVideoBlack(canvas, video, startX, startY, grabbedWidth, grabbedHeight)
+{
+ canvas.width = video.videoWidth;
+ canvas.height = video.videoHeight;
+ if (!grabbedHeight) {
+ startX = 10;
+ startY = 10;
+ grabbedWidth = canvas.width - 20;
+ grabbedHeight = canvas.height - 20;
+ }
+
+ canvas.getContext('2d').drawImage(video, 0, 0, canvas.width, canvas.height);
+
+ imageData = canvas.getContext('2d').getImageData(startX, startY, grabbedWidth, grabbedHeight);
+ data = ""
+ for (var cptr = 0; cptr < grabbedWidth * grabbedHeight; ++cptr) {
+ // Approximatively black pixels.
+ if (data[4 * cptr] > 30 || data[4 * cptr + 1] > 30 || data[4 * cptr + 2] > 30)
+ return false;
+ }
+ return true;
+}
+
+async function checkVideoBlack(expected, canvas, video, errorMessage, counter)
+{
+ if (isVideoBlack(canvas, video) === expected)
+ return Promise.resolve();
+
+ if (counter === undefined)
+ counter = 0;
+ if (counter > 400) {
+ if (!errorMessage)
+ errorMessage = "checkVideoBlack timed out expecting " + expected;
+ return Promise.reject(errorMessage);
+ }
+
+ await waitFor(50);
+ return checkVideoBlack(expected, canvas, video, errorMessage, ++counter);
+}
+
+promise_test(async (test) => {
+ const stream = await navigator.mediaDevices.getUserMedia({ audio: true, video: false });
+
+ const localTrack = stream.getAudioTracks()[0];
+ localTrack.enabled = false;
+ setTimeout(() => localTrack.enabled = false, 0);
+ const recorder = new MediaRecorder(stream);
+ const dataPromise = new Promise(resolve => recorder._ondataavailable_ = (e) => resolve(e.data));
+
+ recorder.start();
+ await waitFor(1000);
+ recorder.stop();
+ const blob = await dataPromise;
+
+ const url = ""
+ video1.src = ""
+ await video1.play();
+
+ assert_greater_than(video1.duration, 0.5);
+
+ const results = await doHumAnalysis(video1, false);
+ assert_true(results, "Should not hear hum");
+
+ URL.revokeObjectURL(url);
+}, "Recording a muted audio track should prodcue silence");
+
+promise_test(async (test) => {
+ const stream = await navigator.mediaDevices.getUserMedia({ audio: true, video: true });
+
+ const localTrack = stream.getAudioTracks()[0];
+ setTimeout(() => localTrack.enabled = false, 50);
+ const recorder = new MediaRecorder(stream);
+ const dataPromise = new Promise(resolve => recorder._ondataavailable_ = (e) => resolve(e.data));
+
+ recorder.start();
+ await waitFor(1000);
+ recorder.stop();
+ const blob = await dataPromise;
+
+ const url = ""
+ video2.src = ""
+ await video2.play();
+
+ assert_greater_than(video2.duration, 0.5);
+
+ const results = await doHumAnalysis(video2, false);
+ assert_true(results, "Should not hear hum");
+
+ URL.revokeObjectURL(url);
+}, "Muting an audio track should record silence");
+
+promise_test(async (test) => {
+ const stream = await navigator.mediaDevices.getUserMedia({ audio: true, video: true });
+
+ const localTrack = stream.getVideoTracks()[0];
+ setTimeout(() => localTrack.enabled = false, 50);
+ const recorder = new MediaRecorder(stream);
+ const dataPromise = new Promise(resolve => recorder._ondataavailable_ = (e) => resolve(e.data));
+
+ recorder.start();
+ await waitFor(1000);
+ recorder.stop();
+ const blob = await dataPromise;
+
+ const url = ""
+ video3.src = ""
+ await video3.play();
+
+ assert_greater_than(video3.duration, 0.5);
+
+ const result = await checkVideoBlack(true, canvas3, video3, "muted video should produce black frames");
+
+ URL.revokeObjectURL(url);
+}, "Muting a video track should produce black frames");
+
+ </script>
+</body>
+</html>
Modified: branches/safari-610-branch/Source/WebCore/ChangeLog (268105 => 268106)
--- branches/safari-610-branch/Source/WebCore/ChangeLog 2020-10-07 01:02:55 UTC (rev 268105)
+++ branches/safari-610-branch/Source/WebCore/ChangeLog 2020-10-07 01:02:59 UTC (rev 268106)
@@ -1,5 +1,85 @@
2020-10-06 Alan Coon <[email protected]>
+ Cherry-pick r267987. rdar://problem/70025699
+
+ MediaRecorder should respect enabled and muted tracks
+ https://bugs.webkit.org/show_bug.cgi?id=217312
+
+ Reviewed by Eric Carlson.
+
+ Source/WebCore:
+
+ If track is muted, replace it by either silence (audio buffer filled with zeros) or black frames.
+ MediaRecorderPrivate will keep track of whether the selected track should be muted.
+ It is then the responsibility of the specialization to do the appropriate processing.
+
+ Test: http/wpt/mediarecorder/mute-tracks.html
+
+ * Modules/mediarecorder/MediaRecorder.cpp:
+ (WebCore::MediaRecorder::trackMutedChanged):
+ (WebCore::MediaRecorder::trackEnabledChanged):
+ * Modules/mediarecorder/MediaRecorder.h:
+ * platform/audio/cocoa/WebAudioBufferList.cpp:
+ (WebCore::WebAudioBufferList::zeroFlatBuffer):
+ * platform/audio/cocoa/WebAudioBufferList.h:
+ * platform/mediarecorder/MediaRecorderPrivate.cpp:
+ (WebCore::MediaRecorderPrivate::selectTracks):
+ (WebCore::MediaRecorderPrivate::checkTrackState):
+ * platform/mediarecorder/MediaRecorderPrivate.h:
+ (WebCore::MediaRecorderPrivate::trackMutedChanged):
+ (WebCore::MediaRecorderPrivate::trackEnabledChanged):
+ (WebCore::MediaRecorderPrivate::shouldMuteAudio const):
+ (WebCore::MediaRecorderPrivate::shouldMuteVideo const):
+ * platform/mediarecorder/MediaRecorderPrivateAVFImpl.cpp:
+ (WebCore::MediaRecorderPrivateAVFImpl::create):
+ (WebCore::MediaRecorderPrivateAVFImpl::videoSampleAvailable):
+ (WebCore::MediaRecorderPrivateAVFImpl::audioSamplesAvailable):
+ * platform/mediarecorder/MediaRecorderPrivateAVFImpl.h:
+
+ LayoutTests:
+
+ * http/wpt/mediarecorder/mute-tracks-expected.txt: Added.
+ * http/wpt/mediarecorder/mute-tracks.html: Added.
+
+
+ git-svn-id: https://svn.webkit.org/repository/webkit/trunk@267987 268f45cc-cd09-0410-ab3c-d52691b4dbfc
+
+ 2020-10-05 Youenn Fablet <[email protected]>
+
+ MediaRecorder should respect enabled and muted tracks
+ https://bugs.webkit.org/show_bug.cgi?id=217312
+
+ Reviewed by Eric Carlson.
+
+ If track is muted, replace it by either silence (audio buffer filled with zeros) or black frames.
+ MediaRecorderPrivate will keep track of whether the selected track should be muted.
+ It is then the responsibility of the specialization to do the appropriate processing.
+
+ Test: http/wpt/mediarecorder/mute-tracks.html
+
+ * Modules/mediarecorder/MediaRecorder.cpp:
+ (WebCore::MediaRecorder::trackMutedChanged):
+ (WebCore::MediaRecorder::trackEnabledChanged):
+ * Modules/mediarecorder/MediaRecorder.h:
+ * platform/audio/cocoa/WebAudioBufferList.cpp:
+ (WebCore::WebAudioBufferList::zeroFlatBuffer):
+ * platform/audio/cocoa/WebAudioBufferList.h:
+ * platform/mediarecorder/MediaRecorderPrivate.cpp:
+ (WebCore::MediaRecorderPrivate::selectTracks):
+ (WebCore::MediaRecorderPrivate::checkTrackState):
+ * platform/mediarecorder/MediaRecorderPrivate.h:
+ (WebCore::MediaRecorderPrivate::trackMutedChanged):
+ (WebCore::MediaRecorderPrivate::trackEnabledChanged):
+ (WebCore::MediaRecorderPrivate::shouldMuteAudio const):
+ (WebCore::MediaRecorderPrivate::shouldMuteVideo const):
+ * platform/mediarecorder/MediaRecorderPrivateAVFImpl.cpp:
+ (WebCore::MediaRecorderPrivateAVFImpl::create):
+ (WebCore::MediaRecorderPrivateAVFImpl::videoSampleAvailable):
+ (WebCore::MediaRecorderPrivateAVFImpl::audioSamplesAvailable):
+ * platform/mediarecorder/MediaRecorderPrivateAVFImpl.h:
+
+2020-10-06 Alan Coon <[email protected]>
+
Cherry-pick r267870. rdar://problem/70025703
Add AVAssetWriter SPI header
Modified: branches/safari-610-branch/Source/WebCore/Modules/mediarecorder/MediaRecorder.cpp (268105 => 268106)
--- branches/safari-610-branch/Source/WebCore/Modules/mediarecorder/MediaRecorder.cpp 2020-10-07 01:02:55 UTC (rev 268105)
+++ branches/safari-610-branch/Source/WebCore/Modules/mediarecorder/MediaRecorder.cpp 2020-10-07 01:02:59 UTC (rev 268106)
@@ -300,6 +300,18 @@
stopRecording();
}
+void MediaRecorder::trackMutedChanged(MediaStreamTrackPrivate& track)
+{
+ if (m_private)
+ m_private->trackMutedChanged(track);
+}
+
+void MediaRecorder::trackEnabledChanged(MediaStreamTrackPrivate& track)
+{
+ if (m_private)
+ m_private->trackEnabledChanged(track);
+}
+
bool MediaRecorder::virtualHasPendingActivity() const
{
return m_state != RecordingState::Inactive;
Modified: branches/safari-610-branch/Source/WebCore/Modules/mediarecorder/MediaRecorder.h (268105 => 268106)
--- branches/safari-610-branch/Source/WebCore/Modules/mediarecorder/MediaRecorder.h 2020-10-07 01:02:55 UTC (rev 268105)
+++ branches/safari-610-branch/Source/WebCore/Modules/mediarecorder/MediaRecorder.h 2020-10-07 01:02:59 UTC (rev 268106)
@@ -108,9 +108,9 @@
// MediaStreamTrackPrivate::Observer
void trackEnded(MediaStreamTrackPrivate&) final;
- void trackMutedChanged(MediaStreamTrackPrivate&) final { };
+ void trackMutedChanged(MediaStreamTrackPrivate&) final;
+ void trackEnabledChanged(MediaStreamTrackPrivate&) final;
void trackSettingsChanged(MediaStreamTrackPrivate&) final { };
- void trackEnabledChanged(MediaStreamTrackPrivate&) final { };
static CreatorFunction m_customCreator;
Modified: branches/safari-610-branch/Source/WebCore/platform/audio/cocoa/WebAudioBufferList.cpp (268105 => 268106)
--- branches/safari-610-branch/Source/WebCore/platform/audio/cocoa/WebAudioBufferList.cpp 2020-10-07 01:02:55 UTC (rev 268105)
+++ branches/safari-610-branch/Source/WebCore/platform/audio/cocoa/WebAudioBufferList.cpp 2020-10-07 01:02:59 UTC (rev 268106)
@@ -146,4 +146,9 @@
return nullptr;
}
+void WebAudioBufferList::zeroFlatBuffer()
+{
+ memset(m_flatBuffer.data(), 0, m_flatBuffer.capacity());
}
+
+}
Modified: branches/safari-610-branch/Source/WebCore/platform/audio/cocoa/WebAudioBufferList.h (268105 => 268106)
--- branches/safari-610-branch/Source/WebCore/platform/audio/cocoa/WebAudioBufferList.h 2020-10-07 01:02:55 UTC (rev 268105)
+++ branches/safari-610-branch/Source/WebCore/platform/audio/cocoa/WebAudioBufferList.h 2020-10-07 01:02:59 UTC (rev 268106)
@@ -58,6 +58,8 @@
WEBCORE_EXPORT static bool isSupportedDescription(const CAAudioStreamDescription&, uint32_t sampleCount);
+ void zeroFlatBuffer();
+
private:
Kind kind() const { return Kind::WebAudioBufferList; }
Modified: branches/safari-610-branch/Source/WebCore/platform/mediarecorder/MediaRecorderPrivate.cpp (268105 => 268106)
--- branches/safari-610-branch/Source/WebCore/platform/mediarecorder/MediaRecorderPrivate.cpp 2020-10-07 01:02:55 UTC (rev 268105)
+++ branches/safari-610-branch/Source/WebCore/platform/mediarecorder/MediaRecorderPrivate.cpp 2020-10-07 01:02:59 UTC (rev 268106)
@@ -36,7 +36,7 @@
{
AudioVideoSelectedTracks selectedTracks;
stream.forEachTrack([&](auto& track) {
- if (!track.enabled() || track.ended())
+ if (track.ended())
return;
switch (track.type()) {
case RealtimeMediaSource::Type::Video: {
@@ -56,6 +56,16 @@
return selectedTracks;
}
+void MediaRecorderPrivate::checkTrackState(const MediaStreamTrackPrivate& track)
+{
+ if (&track.source() == m_audioSource.get()) {
+ m_shouldMuteAudio = track.muted() || !track.enabled();
+ return;
+ }
+ if (&track.source() == m_videoSource.get())
+ m_shouldMuteVideo = track.muted() || !track.enabled();
+}
+
} // namespace WebCore
#endif // ENABLE(MEDIA_STREAM)
Modified: branches/safari-610-branch/Source/WebCore/platform/mediarecorder/MediaRecorderPrivate.h (268105 => 268106)
--- branches/safari-610-branch/Source/WebCore/platform/mediarecorder/MediaRecorderPrivate.h 2020-10-07 01:02:55 UTC (rev 268105)
+++ branches/safari-610-branch/Source/WebCore/platform/mediarecorder/MediaRecorderPrivate.h 2020-10-07 01:02:59 UTC (rev 268106)
@@ -65,11 +65,21 @@
using StartRecordingCallback = CompletionHandler<void(ExceptionOr<String>&&)>;
virtual void startRecording(StartRecordingCallback&& callback) { callback(String(mimeType())); }
+ void trackMutedChanged(MediaStreamTrackPrivate& track) { checkTrackState(track); }
+ void trackEnabledChanged(MediaStreamTrackPrivate& track) { checkTrackState(track); }
+
protected:
void setAudioSource(RefPtr<RealtimeMediaSource>&&);
void setVideoSource(RefPtr<RealtimeMediaSource>&&);
+ void checkTrackState(const MediaStreamTrackPrivate&);
+
+ bool shouldMuteAudio() const { return m_shouldMuteAudio; }
+ bool shouldMuteVideo() const { return m_shouldMuteVideo; }
+
private:
+ bool m_shouldMuteAudio { false };
+ bool m_shouldMuteVideo { false };
RefPtr<RealtimeMediaSource> m_audioSource;
RefPtr<RealtimeMediaSource> m_videoSource;
};
Modified: branches/safari-610-branch/Source/WebCore/platform/mediarecorder/MediaRecorderPrivateAVFImpl.cpp (268105 => 268106)
--- branches/safari-610-branch/Source/WebCore/platform/mediarecorder/MediaRecorderPrivateAVFImpl.cpp 2020-10-07 01:02:55 UTC (rev 268105)
+++ branches/safari-610-branch/Source/WebCore/platform/mediarecorder/MediaRecorderPrivateAVFImpl.cpp 2020-10-07 01:02:59 UTC (rev 268106)
@@ -29,13 +29,20 @@
#if ENABLE(MEDIA_STREAM) && HAVE(AVASSETWRITERDELEGATE)
#include "AudioStreamDescription.h"
+#include "CAAudioStreamDescription.h"
+#include "Logging.h"
#include "MediaRecorderPrivateWriterCocoa.h"
-#include "MediaSample.h"
+#include "MediaSampleAVFObjC.h"
#include "MediaStreamPrivate.h"
+#include "RealtimeIncomingVideoSourceCocoa.h"
#include "SharedBuffer.h"
#include "WebAudioBufferList.h"
+#include "CoreVideoSoftLink.h"
+#include <pal/cf/CoreMediaSoftLink.h>
+
namespace WebCore {
+using namespace PAL;
std::unique_ptr<MediaRecorderPrivateAVFImpl> MediaRecorderPrivateAVFImpl::create(MediaStreamPrivate& stream, const MediaRecorderPrivateOptions& options)
{
@@ -50,10 +57,14 @@
return nullptr;
auto recorder = std::unique_ptr<MediaRecorderPrivateAVFImpl>(new MediaRecorderPrivateAVFImpl(writer.releaseNonNull()));
- if (selectedTracks.audioTrack)
+ if (selectedTracks.audioTrack) {
recorder->setAudioSource(&selectedTracks.audioTrack->source());
- if (selectedTracks.videoTrack)
+ recorder->checkTrackState(*selectedTracks.audioTrack);
+ }
+ if (selectedTracks.videoTrack) {
recorder->setVideoSource(&selectedTracks.videoTrack->source());
+ recorder->checkTrackState(*selectedTracks.videoTrack);
+ }
return recorder;
}
@@ -70,6 +81,37 @@
void MediaRecorderPrivateAVFImpl::videoSampleAvailable(MediaSample& sampleBuffer)
{
+ if (shouldMuteVideo()) {
+ if (!m_blackFrame) {
+ m_blackFrameDescription = CMSampleBufferGetFormatDescription(sampleBuffer.platformSample().sample.cmSampleBuffer);
+ auto dimensions = CMVideoFormatDescriptionGetDimensions(m_blackFrameDescription.get());
+ m_blackFrame = createBlackPixelBuffer(dimensions.width, dimensions.height);
+
+ CMVideoFormatDescriptionRef formatDescription = nullptr;
+ auto status = CMVideoFormatDescriptionCreateForImageBuffer(kCFAllocatorDefault, m_blackFrame.get(), &formatDescription);
+ if (status != noErr) {
+ RELEASE_LOG_ERROR(Media, "MediaRecorderPrivateAVFImpl::videoSampleAvailable ::unable to create a black frame description: %d", static_cast<int>(status));
+ m_blackFrame = nullptr;
+ return;
+ }
+ m_blackFrameDescription = adoptCF(formatDescription);
+ }
+
+ CMSampleBufferRef sample = nullptr;
+ CMSampleTimingInfo timingInfo { kCMTimeInvalid, toCMTime(sampleBuffer.presentationTime()), toCMTime(sampleBuffer.decodeTime()) };
+ auto status = CMSampleBufferCreateReadyWithImageBuffer(kCFAllocatorDefault, (CVImageBufferRef)m_blackFrame.get(), m_blackFrameDescription.get(), &timingInfo, &sample);
+
+ if (status != noErr) {
+ RELEASE_LOG_ERROR(MediaStream, "MediaRecorderPrivateAVFImpl::videoSampleAvailable - unable to create a black frame: %d", static_cast<int>(status));
+ return;
+ }
+ auto newSample = adoptCF(sample);
+ m_writer->appendVideoSampleBuffer(MediaSampleAVFObjC::create(newSample.get(), sampleBuffer.videoRotation(), sampleBuffer.videoMirrored()));
+ return;
+ }
+
+ m_blackFrame = nullptr;
+ m_blackFrameDescription = nullptr;
m_writer->appendVideoSampleBuffer(sampleBuffer);
}
@@ -77,6 +119,18 @@
{
ASSERT(is<WebAudioBufferList>(data));
ASSERT(description.platformDescription().type == PlatformDescription::CAAudioStreamBasicType);
+
+ if (shouldMuteAudio()) {
+ if (!m_audioBuffer || m_description != toCAAudioStreamDescription(description)) {
+ m_description = toCAAudioStreamDescription(description);
+ m_audioBuffer = makeUnique<WebAudioBufferList>(m_description, sampleCount);
+ } else
+ m_audioBuffer->setSampleCount(sampleCount);
+ m_audioBuffer->zeroFlatBuffer();
+ m_writer->appendAudioSampleBuffer(*m_audioBuffer, description, mediaTime, sampleCount);
+ return;
+ }
+
m_writer->appendAudioSampleBuffer(data, description, mediaTime, sampleCount);
}
Modified: branches/safari-610-branch/Source/WebCore/platform/mediarecorder/MediaRecorderPrivateAVFImpl.h (268105 => 268106)
--- branches/safari-610-branch/Source/WebCore/platform/mediarecorder/MediaRecorderPrivateAVFImpl.h 2020-10-07 01:02:55 UTC (rev 268105)
+++ branches/safari-610-branch/Source/WebCore/platform/mediarecorder/MediaRecorderPrivateAVFImpl.h 2020-10-07 01:02:59 UTC (rev 268106)
@@ -26,12 +26,17 @@
#if ENABLE(MEDIA_STREAM) && HAVE(AVASSETWRITERDELEGATE)
+#include "CAAudioStreamDescription.h"
#include "MediaRecorderPrivate.h"
#include "MediaRecorderPrivateWriterCocoa.h"
+using CVPixelBufferRef = struct __CVBuffer*;
+typedef const struct opaqueCMFormatDescription* CMFormatDescriptionRef;
+
namespace WebCore {
class MediaStreamPrivate;
+class WebAudioBufferList;
class MediaRecorderPrivateAVFImpl final
: public MediaRecorderPrivate {
@@ -53,6 +58,10 @@
void stopRecording();
Ref<MediaRecorderPrivateWriter> m_writer;
+ RetainPtr<CVPixelBufferRef> m_blackFrame;
+ RetainPtr<CMFormatDescriptionRef> m_blackFrameDescription;
+ CAAudioStreamDescription m_description;
+ std::unique_ptr<WebAudioBufferList> m_audioBuffer;
};
} // namespace WebCore