Introduce MediaStreamPrivate::forEachTrack
authoryouenn@apple.com <youenn@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 15 Feb 2020 01:01:05 +0000 (01:01 +0000)
committeryouenn@apple.com <youenn@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 15 Feb 2020 01:01:05 +0000 (01:01 +0000)
https://bugs.webkit.org/show_bug.cgi?id=207773

Reviewed by Eric Carlson.

Source/WebCore:

Introduce forEachTrack to allow read-only iterating through the tracks.
This is more efficient than copying the tracks.
Add a helper routine to select the tracks to record in MediaRecorderPrivate.
No change of behavior.

* Sources.txt:
* WebCore.xcodeproj/project.pbxproj:
* platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaStreamAVFObjC.mm:
(WebCore::MediaPlayerPrivateMediaStreamAVFObjC::currentReadyState):
* platform/mediarecorder/MediaRecorderPrivate.cpp: Added.
(WebCore::MediaRecorderPrivate::selectTracks):
* platform/mediarecorder/MediaRecorderPrivate.h:
* platform/mediarecorder/MediaRecorderPrivateAVFImpl.cpp:
(WebCore::MediaRecorderPrivateAVFImpl::create):
* platform/mediastream/MediaStreamPrivate.cpp:
(WebCore::MediaStreamPrivate::forEachTrack const):
* platform/mediastream/MediaStreamPrivate.h:

Source/WebKit:

* WebProcess/GPU/webrtc/MediaRecorderPrivate.cpp:
(WebKit::MediaRecorderPrivate::MediaRecorderPrivate):
Use helper routine instead of MediaStreamPrviate::streamTracks().

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@256658 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WebCore/ChangeLog
Source/WebCore/Sources.txt
Source/WebCore/WebCore.xcodeproj/project.pbxproj
Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaStreamAVFObjC.mm
Source/WebCore/platform/mediarecorder/MediaRecorderPrivate.cpp [new file with mode: 0644]
Source/WebCore/platform/mediarecorder/MediaRecorderPrivate.h
Source/WebCore/platform/mediarecorder/MediaRecorderPrivateAVFImpl.cpp
Source/WebCore/platform/mediastream/MediaStreamPrivate.cpp
Source/WebCore/platform/mediastream/MediaStreamPrivate.h
Source/WebKit/ChangeLog
Source/WebKit/WebProcess/GPU/webrtc/MediaRecorderPrivate.cpp

index 07d9a6b..4aa31c2 100644 (file)
@@ -1,3 +1,28 @@
+2020-02-14  Youenn Fablet  <youenn@apple.com>
+
+        Introduce MediaStreamPrivate::forEachTrack
+        https://bugs.webkit.org/show_bug.cgi?id=207773
+
+        Reviewed by Eric Carlson.
+
+        Introduce forEachTrack to allow read-only iterating through the tracks.
+        This is more efficient than copying the tracks.
+        Add a helper routine to select the tracks to record in MediaRecorderPrivate.
+        No change of behavior.
+
+        * Sources.txt:
+        * WebCore.xcodeproj/project.pbxproj:
+        * platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaStreamAVFObjC.mm:
+        (WebCore::MediaPlayerPrivateMediaStreamAVFObjC::currentReadyState):
+        * platform/mediarecorder/MediaRecorderPrivate.cpp: Added.
+        (WebCore::MediaRecorderPrivate::selectTracks):
+        * platform/mediarecorder/MediaRecorderPrivate.h:
+        * platform/mediarecorder/MediaRecorderPrivateAVFImpl.cpp:
+        (WebCore::MediaRecorderPrivateAVFImpl::create):
+        * platform/mediastream/MediaStreamPrivate.cpp:
+        (WebCore::MediaStreamPrivate::forEachTrack const):
+        * platform/mediastream/MediaStreamPrivate.h:
+
 2020-02-14  Pavel Feldman  <pavel.feldman@gmail.com>
 
         [Curl] Implement NetworkStorageSession::get/set/deleteCookie
index 1a04916..fbf72f6 100644 (file)
@@ -1965,6 +1965,7 @@ platform/graphics/transforms/TranslateTransformOperation.cpp
 platform/mediacapabilities/MediaEngineConfigurationFactory.cpp
 platform/mediacapabilities/MediaCapabilitiesLogging.cpp
 
+platform/mediarecorder/MediaRecorderPrivate.cpp
 platform/mediarecorder/MediaRecorderPrivateMock.cpp
 
 platform/mediastream/AudioMediaStreamTrackRenderer.cpp
index 4a36477..61102a4 100644 (file)
                4176900422FCD8F200B1576D /* MediaSourceRegistry.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MediaSourceRegistry.cpp; sourceTree = "<group>"; };
                4176E88F23C348D2003E83FE /* MediaRecorderProvider.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MediaRecorderProvider.h; sourceTree = "<group>"; };
                4176E89123C34B75003E83FE /* MediaRecorderProvider.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = MediaRecorderProvider.cpp; sourceTree = "<group>"; };
+               4177040B23F70CAB000C54EE /* MediaRecorderPrivate.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MediaRecorderPrivate.cpp; sourceTree = "<group>"; };
                4177F51C2382544000C04486 /* BaseAudioSharedUnit.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = BaseAudioSharedUnit.cpp; sourceTree = "<group>"; };
                4177F51E2382545E00C04486 /* BaseAudioSharedUnit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BaseAudioSharedUnit.h; sourceTree = "<group>"; };
                417DA4CE13734326007C57FB /* Internals.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Internals.h; sourceTree = "<group>"; };
                        isa = PBXGroup;
                        children = (
                                4D3C05D421AF480900F2890A /* cocoa */,
+                               4177040B23F70CAB000C54EE /* MediaRecorderPrivate.cpp */,
                                4D3B5014217E58B700665DB1 /* MediaRecorderPrivate.h */,
                                4D73F945218BC5FA003A3ED6 /* MediaRecorderPrivateAVFImpl.cpp */,
                                4D73F944218BC5FA003A3ED6 /* MediaRecorderPrivateAVFImpl.h */,
index 61887f7..48a6943 100644 (file)
@@ -630,19 +630,19 @@ MediaPlayer::ReadyState MediaPlayerPrivateMediaStreamAVFObjC::readyState() const
 
 MediaPlayer::ReadyState MediaPlayerPrivateMediaStreamAVFObjC::currentReadyState()
 {
-    if (!m_mediaStreamPrivate || !m_mediaStreamPrivate->active() || !m_mediaStreamPrivate->tracks().size())
+    if (!m_mediaStreamPrivate || !m_mediaStreamPrivate->active() || !m_mediaStreamPrivate->hasTracks())
         return MediaPlayer::ReadyState::HaveNothing;
 
-    bool allTracksAreLive = true;
-    for (auto& track : m_mediaStreamPrivate->tracks()) {
-        if (!track->enabled() || track->readyState() != MediaStreamTrackPrivate::ReadyState::Live)
-            allTracksAreLive = false;
+    bool waitingForImage = m_mediaStreamPrivate->activeVideoTrack() && !m_imagePainter.mediaSample;
+    if (waitingForImage && (!m_haveSeenMetadata || m_waitingForFirstImage))
+        return MediaPlayer::ReadyState::HaveNothing;
 
-        if (track == m_mediaStreamPrivate->activeVideoTrack() && !m_imagePainter.mediaSample) {
-            if (!m_haveSeenMetadata || m_waitingForFirstImage)
-                return MediaPlayer::ReadyState::HaveNothing;
-            allTracksAreLive = false;
-        }
+    bool allTracksAreLive = !waitingForImage;
+    if (allTracksAreLive) {
+        m_mediaStreamPrivate->forEachTrack([&](auto& track) {
+            if (!track.enabled() || track.readyState() != MediaStreamTrackPrivate::ReadyState::Live)
+                allTracksAreLive = false;
+        });
     }
 
     if (m_waitingForFirstImage || (!allTracksAreLive && !m_haveSeenMetadata))
diff --git a/Source/WebCore/platform/mediarecorder/MediaRecorderPrivate.cpp b/Source/WebCore/platform/mediarecorder/MediaRecorderPrivate.cpp
new file mode 100644 (file)
index 0000000..a6993ca
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * 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.
+ */
+
+
+#include "config.h"
+#include "MediaRecorderPrivate.h"
+
+#if ENABLE(MEDIA_STREAM)
+
+#include "MediaStreamPrivate.h"
+
+namespace WebCore {
+
+MediaRecorderPrivate::AudioVideoSelectedTracks MediaRecorderPrivate::selectTracks(const MediaStreamPrivate& stream)
+{
+    AudioVideoSelectedTracks selectedTracks;
+    stream.forEachTrack([&](auto& track) {
+        if (!track.enabled() || track.ended())
+            return;
+        switch (track.type()) {
+        case RealtimeMediaSource::Type::Video: {
+            auto& settings = track.settings();
+            if (!selectedTracks.videoTrack && settings.supportsWidth() && settings.supportsHeight())
+                selectedTracks.videoTrack = &track;
+            break;
+        }
+        case RealtimeMediaSource::Type::Audio:
+            if (!selectedTracks.audioTrack)
+                selectedTracks.audioTrack = &track;
+            break;
+        case RealtimeMediaSource::Type::None:
+            break;
+        }
+    });
+    return selectedTracks;
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(MEDIA_STREAM)
index ad51807..60430b4 100644 (file)
@@ -38,6 +38,7 @@ namespace WebCore {
 
 class AudioStreamDescription;
 class MediaSample;
+class MediaStreamPrivate;
 class MediaStreamTrackPrivate;
 class PlatformAudioData;
 class SharedBuffer;
@@ -46,6 +47,12 @@ class MediaRecorderPrivate {
 public:
     virtual ~MediaRecorderPrivate() = default;
 
+    struct AudioVideoSelectedTracks {
+        const MediaStreamTrackPrivate* audioTrack { nullptr };
+        const MediaStreamTrackPrivate* videoTrack { nullptr };
+    };
+    WEBCORE_EXPORT static AudioVideoSelectedTracks selectTracks(const MediaStreamPrivate&);
+
     virtual void sampleBufferUpdated(const MediaStreamTrackPrivate&, MediaSample&) = 0;
     virtual void audioSamplesAvailable(const MediaStreamTrackPrivate&, const WTF::MediaTime&, const PlatformAudioData&, const AudioStreamDescription&, size_t) = 0;
 
@@ -58,7 +65,7 @@ public:
 protected:
     ErrorCallback m_errorCallback;
 };
-    
+
 } // namespace WebCore
 
 #endif // ENABLE(MEDIA_STREAM)
index 73f1d0a..2d5a359 100644 (file)
@@ -42,36 +42,19 @@ std::unique_ptr<MediaRecorderPrivateAVFImpl> MediaRecorderPrivateAVFImpl::create
     // Currently we only choose the first track as the recorded track.
     // FIXME: We would better to throw an exception to JavaScript if writer creation fails.
 
-    String audioTrackId;
-    String videoTrackId;
-    const MediaStreamTrackPrivate* audioTrack { nullptr };
-    const MediaStreamTrackPrivate* videoTrack { nullptr };
-    for (auto& track : stream.tracks()) {
-        if (!track->enabled() || track->ended())
-            continue;
-        switch (track->type()) {
-        case RealtimeMediaSource::Type::Video: {
-            auto& settings = track->settings();
-            if (!videoTrack && settings.supportsWidth() && settings.supportsHeight()) {
-                videoTrack = track.get();
-                videoTrackId = videoTrack->id();
-            }
-            break;
-        }
-        case RealtimeMediaSource::Type::Audio:
-            if (!audioTrack) {
-                audioTrack = track.get();
-                audioTrackId = audioTrack->id();
-            }
-            break;
-        case RealtimeMediaSource::Type::None:
-            break;
-        }
-    }
-    auto writer = MediaRecorderPrivateWriter::create(audioTrack, videoTrack);
+    auto selectedTracks = MediaRecorderPrivate::selectTracks(stream);
+
+    auto writer = MediaRecorderPrivateWriter::create(selectedTracks.audioTrack, selectedTracks.videoTrack);
     if (!writer)
         return nullptr;
 
+    String audioTrackId;
+    if (selectedTracks.audioTrack)
+        audioTrackId = selectedTracks.audioTrack->id();
+    String videoTrackId;
+    if (selectedTracks.videoTrack)
+        videoTrackId = selectedTracks.videoTrack->id();
+
     return makeUnique<MediaRecorderPrivateAVFImpl>(writer.releaseNonNull(), WTFMove(audioTrackId), WTFMove(videoTrackId));
 }
 
index ccb4606..fc199d1 100644 (file)
@@ -116,6 +116,12 @@ MediaStreamTrackPrivateVector MediaStreamPrivate::tracks() const
     return copyToVector(m_trackSet.values());
 }
 
+void MediaStreamPrivate::forEachTrack(const Function<void(const MediaStreamTrackPrivate&)>& callback) const
+{
+    for (auto& track : m_trackSet.values())
+        callback(*track);
+}
+
 void MediaStreamPrivate::updateActiveState(NotifyClientOption notifyClientOption)
 {
     bool newActiveState = false;
index de44d88..470463c 100644 (file)
@@ -81,7 +81,9 @@ public:
 
     String id() const { return m_id; }
 
-    WEBCORE_EXPORT MediaStreamTrackPrivateVector tracks() const;
+    MediaStreamTrackPrivateVector tracks() const;
+    bool hasTracks() const { return !m_trackSet.isEmpty(); }
+    void forEachTrack(const Function<void(const MediaStreamTrackPrivate&)>&) const;
     MediaStreamTrackPrivate* activeVideoTrack() { return m_activeVideoTrack; }
 
     bool active() const { return m_isActive; }
index 173e91e..ec13aff 100644 (file)
@@ -1,3 +1,14 @@
+2020-02-14  Youenn Fablet  <youenn@apple.com>
+
+        Introduce MediaStreamPrivate::forEachTrack
+        https://bugs.webkit.org/show_bug.cgi?id=207773
+
+        Reviewed by Eric Carlson.
+
+        * WebProcess/GPU/webrtc/MediaRecorderPrivate.cpp:
+        (WebKit::MediaRecorderPrivate::MediaRecorderPrivate):
+        Use helper routine instead of MediaStreamPrviate::streamTracks().
+
 2020-02-14  Alex Christensen  <achristensen@webkit.org>
 
         WKWebView._setResourceLoadDelegate should clear the WebPageProxy's ResourceLoadClient
index dd40919..fe43aa8 100644 (file)
@@ -50,32 +50,21 @@ MediaRecorderPrivate::MediaRecorderPrivate(const MediaStreamPrivate& stream)
     // FIXME: we will need to implement support for multiple audio/video tracks
     // Currently we only choose the first track as the recorded track.
 
-    const MediaStreamTrackPrivate* audioTrack { nullptr };
-    const MediaStreamTrackPrivate* videoTrack { nullptr };
-    for (auto& track : stream.tracks()) {
-        if (!track->enabled() || track->ended())
-            continue;
-        switch (track->type()) {
-        case RealtimeMediaSource::Type::Video: {
-            auto& settings = track->settings();
-            if (!videoTrack && settings.supportsWidth() && settings.supportsHeight()) {
-                videoTrack = track.get();
-                m_recordedVideoTrackID = videoTrack->id();
-            }
-            break;
-        }
-        case RealtimeMediaSource::Type::Audio:
-            if (!audioTrack) {
-                m_ringBuffer = makeUnique<CARingBuffer>(makeUniqueRef<SharedRingBufferStorage>(this));
-                audioTrack = track.get();
-                m_recordedAudioTrackID = audioTrack->id();
-            }
-            break;
-        case RealtimeMediaSource::Type::None:
-            break;
-        }
+    auto selectedTracks = MediaRecorderPrivate::selectTracks(stream);
+    if (selectedTracks.audioTrack) {
+        m_ringBuffer = makeUnique<CARingBuffer>(makeUniqueRef<SharedRingBufferStorage>(this));
+        m_recordedAudioTrackID = selectedTracks.audioTrack->id();
     }
-    m_connection->sendWithAsyncReply(Messages::RemoteMediaRecorderManager::CreateRecorder { m_identifier, !!audioTrack, videoTrack ? videoTrack->settings().width() : 0, videoTrack ? videoTrack->settings().height() : 0 }, [this, weakThis = makeWeakPtr(this)](auto&& exception) {
+
+    int width = 0;
+    int height = 0;
+    if (selectedTracks.videoTrack) {
+        m_recordedVideoTrackID = selectedTracks.videoTrack->id();
+        height = selectedTracks.videoTrack->settings().height();
+        width = selectedTracks.videoTrack->settings().width();
+    }
+
+    m_connection->sendWithAsyncReply(Messages::RemoteMediaRecorderManager::CreateRecorder { m_identifier, !!selectedTracks.audioTrack, width, height }, [this, weakThis = makeWeakPtr(this)](auto&& exception) {
         if (!weakThis || !exception)
             return;
         m_errorCallback(Exception { exception->code, WTFMove(exception->message) });