[GStreamer][MediaStream] Handle track addition and removal
[WebKit-https.git] / Source / WebCore / platform / mediastream / gstreamer / GStreamerMediaStreamSource.cpp
index 09a43e6..2513ca9 100644 (file)
@@ -41,6 +41,8 @@ namespace WebCore {
 static void webkitMediaStreamSrcPushVideoSample(WebKitMediaStreamSrc* self, GstSample* gstsample);
 static void webkitMediaStreamSrcPushAudioSample(WebKitMediaStreamSrc* self, GstSample* gstsample);
 static void webkitMediaStreamSrcTrackEnded(WebKitMediaStreamSrc* self, MediaStreamTrackPrivate&);
+static void webkitMediaStreamSrcAddTrack(WebKitMediaStreamSrc* self, MediaStreamTrackPrivate*);
+static void webkitMediaStreamSrcRemoveTrackByType(WebKitMediaStreamSrc* self, RealtimeMediaSource::Type trackType);
 
 static GstStaticPadTemplate videoSrcTemplate = GST_STATIC_PAD_TEMPLATE("video_src",
     GST_PAD_SRC,
@@ -93,7 +95,7 @@ GstStream* webkitMediaStreamNew(MediaStreamTrackPrivate* track)
         caps = adoptGRef(gst_static_pad_template_get_caps(&videoSrcTemplate));
         type = GST_STREAM_TYPE_VIDEO;
     } else {
-        GST_FIXME("Handle %d type", (gint) track->type());
+        GST_FIXME("Handle %d type", static_cast<int>(track->type()));
 
         return nullptr;
     }
@@ -142,6 +144,30 @@ private:
     WebKitMediaStreamSrc* m_mediaStreamSrc;
 };
 
+class WebKitMediaStreamObserver
+    : public MediaStreamPrivate::Observer {
+public:
+    virtual ~WebKitMediaStreamObserver() { };
+    WebKitMediaStreamObserver(WebKitMediaStreamSrc* src)
+        : m_mediaStreamSrc(src) { }
+
+    void characteristicsChanged() final { GST_DEBUG_OBJECT(m_mediaStreamSrc.get(), "renegotiation should happen"); }
+    void activeStatusChanged() final { }
+
+    void didAddTrack(MediaStreamTrackPrivate& track) final
+    {
+        webkitMediaStreamSrcAddTrack(m_mediaStreamSrc.get(), &track);
+    }
+
+    void didRemoveTrack(MediaStreamTrackPrivate& track) final
+    {
+        webkitMediaStreamSrcRemoveTrackByType(m_mediaStreamSrc.get(), track.type());
+    }
+
+private:
+    GRefPtr<WebKitMediaStreamSrc> m_mediaStreamSrc;
+};
+
 typedef struct _WebKitMediaStreamSrcClass WebKitMediaStreamSrcClass;
 struct _WebKitMediaStreamSrc {
     GstBin parent_instance;
@@ -153,7 +179,8 @@ struct _WebKitMediaStreamSrc {
     GstElement* videoSrc;
     GstClockTime firstFramePts;
 
-    std::unique_ptr<WebKitMediaStreamTrackObserver> observer;
+    std::unique_ptr<WebKitMediaStreamTrackObserver> mediaStreamTrackObserver;
+    std::unique_ptr<WebKitMediaStreamObserver> mediaStreamObserver;
     volatile gint npads;
     gulong probeid;
     RefPtr<MediaStreamPrivate> stream;
@@ -266,8 +293,13 @@ static void webkitMediaStreamSrcFinalize(GObject* object)
     WebKitMediaStreamSrc* self = WEBKIT_MEDIA_STREAM_SRC(object);
 
     GST_OBJECT_LOCK(self);
-    for (auto& track : self->stream->tracks())
-        track->removeObserver(*self->observer.get());
+    if (self->stream) {
+        for (auto& track : self->stream->tracks())
+            track->removeObserver(*self->mediaStreamTrackObserver.get());
+
+        self->stream->removeObserver(*self->mediaStreamObserver);
+        self->stream = nullptr;
+    }
     GST_OBJECT_UNLOCK(self);
 
     g_clear_pointer(&self->uri, g_free);
@@ -283,7 +315,7 @@ static GstStateChangeReturn webkitMediaStreamSrcChangeState(GstElement* element,
 
         GST_OBJECT_LOCK(self);
         for (auto& track : self->stream->tracks())
-            track->removeObserver(*self->observer.get());
+            track->removeObserver(*self->mediaStreamTrackObserver.get());
         GST_OBJECT_UNLOCK(self);
     }
 
@@ -319,7 +351,8 @@ static void webkit_media_stream_src_class_init(WebKitMediaStreamSrcClass* klass)
 
 static void webkit_media_stream_src_init(WebKitMediaStreamSrc* self)
 {
-    self->observer = std::make_unique<WebKitMediaStreamTrackObserver>(self);
+    self->mediaStreamTrackObserver = std::make_unique<WebKitMediaStreamTrackObserver>(self);
+    self->mediaStreamObserver = std::make_unique<WebKitMediaStreamObserver>(self);
     self->flowCombiner = gst_flow_combiner_new();
     self->firstAudioBufferPts = GST_CLOCK_TIME_NONE;
     self->firstFramePts = GST_CLOCK_TIME_NONE;
@@ -420,7 +453,7 @@ static gboolean webkitMediaStreamSrcSetupSrc(WebKitMediaStreamSrc* self,
         });
 
     if (observe_track)
-        track->addObserver(*self->observer.get());
+        track->addObserver(*self->mediaStreamTrackObserver.get());
 
     gst_element_sync_state_with_parent(element);
     return TRUE;
@@ -451,37 +484,47 @@ static void webkitMediaStreamSrcPostStreamCollection(WebKitMediaStreamSrc* self,
         gst_message_new_stream_collection(GST_OBJECT(self), self->streamCollection.get()));
 }
 
-gboolean webkitMediaStreamSrcSetStream(WebKitMediaStreamSrc* self, MediaStreamPrivate* stream)
+static void webkitMediaStreamSrcAddTrack(WebKitMediaStreamSrc* self, MediaStreamTrackPrivate* track)
 {
-    g_return_val_if_fail(WEBKIT_IS_MEDIA_STREAM_SRC(self), FALSE);
+    if (track->type() == RealtimeMediaSource::Type::Audio)
+        webkitMediaStreamSrcSetupAppSrc(self, track, &self->audioSrc, &audioSrcTemplate);
+    else if (track->type() == RealtimeMediaSource::Type::Video)
+        webkitMediaStreamSrcSetupAppSrc(self, track, &self->videoSrc, &videoSrcTemplate);
+    else
+        GST_INFO("Unsupported track type: %d", static_cast<int>(track->type()));
+}
 
-    if (self->audioSrc) {
-        gst_element_set_state(self->audioSrc, GST_STATE_NULL);
-        gst_bin_remove(GST_BIN(self), self->audioSrc);
-        self->audioSrc = nullptr;
-    }
+static void webkitMediaStreamSrcRemoveTrackByType(WebKitMediaStreamSrc* self, RealtimeMediaSource::Type trackType)
+{
+    if (trackType == RealtimeMediaSource::Type::Audio) {
+        if (self->audioSrc) {
+            gst_element_set_state(self->audioSrc, GST_STATE_NULL);
+            gst_bin_remove(GST_BIN(self), self->audioSrc);
+            self->audioSrc = nullptr;
+        }
+    } else if (trackType == RealtimeMediaSource::Type::Video) {
+        if (self->videoSrc) {
+            gst_element_set_state(self->videoSrc, GST_STATE_NULL);
+            gst_bin_remove(GST_BIN(self), self->videoSrc);
+            self->videoSrc = nullptr;
+        }
+    } else
+        GST_INFO("Unsupported track type: %d", static_cast<int>(trackType));
+}
 
-    if (self->videoSrc) {
-        gst_element_set_state(self->videoSrc, GST_STATE_NULL);
-        gst_bin_remove(GST_BIN(self), self->videoSrc);
-        self->videoSrc = nullptr;
-    }
+bool webkitMediaStreamSrcSetStream(WebKitMediaStreamSrc* self, MediaStreamPrivate* stream)
+{
+    ASSERT(WEBKIT_IS_MEDIA_STREAM_SRC(self));
+
+    webkitMediaStreamSrcRemoveTrackByType(self, RealtimeMediaSource::Type::Audio);
+    webkitMediaStreamSrcRemoveTrackByType(self, RealtimeMediaSource::Type::Video);
 
     webkitMediaStreamSrcPostStreamCollection(self, stream);
 
     self->stream = stream;
-    for (auto& track : stream->tracks()) {
-        if (track->type() == RealtimeMediaSource::Type::Audio) {
-            webkitMediaStreamSrcSetupAppSrc(self, track.get(), &self->audioSrc,
-                &audioSrcTemplate);
-        } else if (track->type() == RealtimeMediaSource::Type::Video) {
-            webkitMediaStreamSrcSetupAppSrc(self, track.get(), &self->videoSrc,
-                &videoSrcTemplate);
-        } else {
-            GST_INFO("Unsuported track type: %d", (gint) track->type());
-            continue;
-        }
-    }
+    self->stream->addObserver(*self->mediaStreamObserver.get());
+    for (auto& track : stream->tracks())
+        webkitMediaStreamSrcAddTrack(self, track.get());
 
     return TRUE;
 }