Skip to content

Commit f1276f1

Browse files
committed
[GStreamer][WebRTC] Emit 'track' event before resolving setRemoteDescription's promise
https://bugs.webkit.org/show_bug.cgi?id=275685 Reviewed by Philippe Normand. The track event should be emitted after sucessfully applying a remote description and before the promise from setRemoteDescription is resolved. However, up until now the GstWebRTC backend emitted the event based on the 'pad-added' signal. The timing of the signal doesn't match what the spec expects. Fix the issue by querying the transceiver states after applying a remote description sucessfully. By providing the transceiver states to PeerConnectionBackend::setRemoteDescriptionSucceeded(), it's able to emit the track events correctly acccording to the spec. A test is added to check that the track event is emitted before setRemoteDescription resolves, which would fail before this patch in the GstWebRTC backend. * LayoutTests/platform/glib/TestExpectations: * LayoutTests/platform/glib/fast/mediastream/RTCPeerConnection-inspect-answer-expected.txt: * LayoutTests/platform/glib/fast/mediastream/RTCPeerConnection-media-setup-single-dialog-expected.txt: * LayoutTests/platform/glib/fast/mediastream/RTCPeerConnection-setRemoteDescription-offer-expected.txt: * LayoutTests/platform/glib/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-setLocalDescription-parameterless.https-expected.txt: Removed. * LayoutTests/platform/glib/imported/w3c/web-platform-tests/webrtc/protocol/split.https-expected.txt: Added. * LayoutTests/webrtc/setRemoteDescription-track-expected.txt: Added. * LayoutTests/webrtc/setRemoteDescription-track.html: Added. * Source/WebCore/Modules/mediastream/PeerConnectionBackend.cpp: (WebCore::PeerConnectionBackend::setRemoteDescriptionSucceeded): (WebCore::PeerConnectionBackend::setRemoteDescriptionFailed): (WebCore::PeerConnectionBackend::stop): (WebCore::PeerConnectionBackend::dispatchTrackEvent): Deleted. (WebCore::PeerConnectionBackend::addPendingTrackEvent): Deleted. * Source/WebCore/Modules/mediastream/PeerConnectionBackend.h: * Source/WebCore/Modules/mediastream/gstreamer/GStreamerMediaEndpoint.cpp: (WebCore::GStreamerMediaEndpoint::initializePipeline): (WebCore::GStreamerMediaEndpointTransceiverState::isolatedCopy): (WebCore::getMediaStreamIdsFromSDPMedia): (WebCore::isRecvDirection): (WebCore::toGStreamerMediaEndpointTransceiverState): (WebCore::transceiverStatesFromWebRTCBin): (WebCore::GStreamerMediaEndpoint::doSetLocalDescription): (WebCore::GStreamerMediaEndpoint::setTransceiverCodecPreferences): (WebCore::GStreamerMediaEndpoint::doSetRemoteDescription): (WebCore::GStreamerMediaEndpoint::setDescription): (WebCore::GStreamerMediaEndpoint::connectIncomingTrack): * Source/WebCore/Modules/mediastream/gstreamer/GStreamerMediaEndpoint.h: * Source/WebCore/Modules/mediastream/gstreamer/GStreamerPeerConnectionBackend.cpp: (WebCore::GStreamerPeerConnectionBackend::addPendingTrackEvent): Deleted. (WebCore::GStreamerPeerConnectionBackend::dispatchPendingTrackEvents): Deleted. * Source/WebCore/Modules/mediastream/gstreamer/GStreamerPeerConnectionBackend.h: * Source/WebCore/platform/mediastream/MediaStreamTrackPrivate.cpp: (WebCore::MediaStreamTrackPrivate::dataFlowStarted): * Source/WebCore/platform/mediastream/MediaStreamTrackPrivate.h: (WebCore::MediaStreamTrackPrivateObserver::dataFlowStarted): * Source/WebCore/platform/mediastream/gstreamer/GStreamerMediaStreamSource.cpp: (webkitMediaStreamSrcCharacteristicsChanged): Canonical link: https://commits.webkit.org/281892@main
1 parent 1485471 commit f1276f1

File tree

9 files changed

+208
-107
lines changed

9 files changed

+208
-107
lines changed

Source/WebCore/Modules/mediastream/PeerConnectionBackend.cpp

Lines changed: 1 addition & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -328,7 +328,7 @@ void PeerConnectionBackend::setRemoteDescriptionSucceeded(std::optional<Descript
328328
DEBUG_LOG(LOGIDENTIFIER, "Transceiver states: ", *transceiverStates);
329329
ASSERT(m_setDescriptionCallback);
330330

331-
m_peerConnection.queueTaskKeepingObjectAlive(m_peerConnection, TaskSource::Networking, [this, callback = WTFMove(m_setDescriptionCallback), descriptionStates = WTFMove(descriptionStates), transceiverStates = WTFMove(transceiverStates), sctpBackend = WTFMove(sctpBackend), maxMessageSize, events = WTFMove(m_pendingTrackEvents)]() mutable {
331+
m_peerConnection.queueTaskKeepingObjectAlive(m_peerConnection, TaskSource::Networking, [this, callback = WTFMove(m_setDescriptionCallback), descriptionStates = WTFMove(descriptionStates), transceiverStates = WTFMove(transceiverStates), sctpBackend = WTFMove(sctpBackend), maxMessageSize]() mutable {
332332
if (m_peerConnection.isClosed())
333333
return;
334334

@@ -402,38 +402,17 @@ void PeerConnectionBackend::setRemoteDescriptionSucceeded(std::optional<Descript
402402

403403
track->source().setMuted(false);
404404
}
405-
} else {
406-
// FIXME: Move ports out of m_pendingTrackEvents.
407-
for (auto& event : events)
408-
dispatchTrackEvent(event);
409405
}
410406

411407
callback({ });
412408
});
413409
}
414410

415-
void PeerConnectionBackend::dispatchTrackEvent(PendingTrackEvent& event)
416-
{
417-
auto& track = event.track.get();
418-
419-
m_peerConnection.dispatchEvent(RTCTrackEvent::create(eventNames().trackEvent, Event::CanBubble::No, Event::IsCancelable::No, WTFMove(event.receiver), WTFMove(event.track), WTFMove(event.streams), WTFMove(event.transceiver)));
420-
ALWAYS_LOG(LOGIDENTIFIER, "Dispatched if feasible track of type ", track.source().type());
421-
422-
if (m_peerConnection.isClosed())
423-
return;
424-
425-
// FIXME: As per spec, we should set muted to 'false' when starting to receive the content from network.
426-
track.source().setMuted(false);
427-
}
428-
429411
void PeerConnectionBackend::setRemoteDescriptionFailed(Exception&& exception)
430412
{
431413
ASSERT(isMainThread());
432414
ALWAYS_LOG(LOGIDENTIFIER, "Set remote description failed:", exception.message());
433415

434-
ASSERT(m_pendingTrackEvents.isEmpty());
435-
m_pendingTrackEvents.clear();
436-
437416
ASSERT(m_setDescriptionCallback);
438417
m_peerConnection.queueTaskKeepingObjectAlive(m_peerConnection, TaskSource::Networking, [this, callback = WTFMove(m_setDescriptionCallback), exception = WTFMove(exception)]() mutable {
439418
if (m_peerConnection.isClosed())
@@ -454,12 +433,6 @@ void PeerConnectionBackend::iceGatheringStateChanged(RTCIceGatheringState state)
454433
});
455434
}
456435

457-
void PeerConnectionBackend::addPendingTrackEvent(PendingTrackEvent&& event)
458-
{
459-
ASSERT(!m_peerConnection.isStopped());
460-
m_pendingTrackEvents.append(WTFMove(event));
461-
}
462-
463436
static String extractIPAddress(StringView sdp)
464437
{
465438
unsigned counter = 0;
@@ -590,8 +563,6 @@ void PeerConnectionBackend::stop()
590563
m_offerAnswerCallback = nullptr;
591564
m_setDescriptionCallback = nullptr;
592565

593-
m_pendingTrackEvents.clear();
594-
595566
doStop();
596567
}
597568

Source/WebCore/Modules/mediastream/PeerConnectionBackend.h

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -228,16 +228,6 @@ class PeerConnectionBackend
228228

229229
void validateSDP(const String&) const;
230230

231-
struct PendingTrackEvent {
232-
Ref<RTCRtpReceiver> receiver;
233-
Ref<MediaStreamTrack> track;
234-
Vector<RefPtr<MediaStream>> streams;
235-
RefPtr<RTCRtpTransceiver> transceiver;
236-
};
237-
void addPendingTrackEvent(PendingTrackEvent&&);
238-
239-
void dispatchTrackEvent(PendingTrackEvent&);
240-
241231
private:
242232
virtual void doCreateOffer(RTCOfferOptions&&) = 0;
243233
virtual void doCreateAnswer(RTCAnswerOptions&&) = 0;
@@ -255,8 +245,6 @@ class PeerConnectionBackend
255245

256246
bool m_shouldFilterICECandidates { true };
257247

258-
Vector<PendingTrackEvent> m_pendingTrackEvents;
259-
260248
#if !RELEASE_LOG_DISABLED
261249
Ref<const Logger> m_logger;
262250
const void* m_logIdentifier;

Source/WebCore/Modules/mediastream/gstreamer/GStreamerMediaEndpoint.cpp

Lines changed: 187 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,10 @@ bool GStreamerMediaEndpoint::initializePipeline()
170170
}), this);
171171

172172
#ifndef GST_DISABLE_GST_DEBUG
173+
g_signal_connect_swapped(m_webrtcBin.get(), "on-new-transceiver", G_CALLBACK(+[](GStreamerMediaEndpoint* endPoint, GstWebRTCRTPTransceiver* transceiver) {
174+
GST_DEBUG_OBJECT(endPoint->m_webrtcBin.get(), "New transceiver: %" GST_PTR_FORMAT, transceiver);
175+
}), this);
176+
173177
g_signal_connect(m_webrtcBin.get(), "notify::connection-state", G_CALLBACK(+[](GstElement* webrtcBin, GParamSpec*, GStreamerMediaEndpoint* endPoint) {
174178
GstWebRTCPeerConnectionState state;
175179
g_object_get(webrtcBin, "connection-state", &state, nullptr);
@@ -370,6 +374,119 @@ static std::optional<PeerConnectionBackend::DescriptionStates> descriptionsFromW
370374
};
371375
}
372376

377+
struct GStreamerMediaEndpointTransceiverState {
378+
String mid;
379+
Vector<String> receiverStreamIds;
380+
std::optional<RTCRtpTransceiverDirection> firedDirection;
381+
382+
GStreamerMediaEndpointTransceiverState isolatedCopy() &&;
383+
};
384+
385+
inline GStreamerMediaEndpointTransceiverState GStreamerMediaEndpointTransceiverState::isolatedCopy() &&
386+
{
387+
return {
388+
WTFMove(mid).isolatedCopy(),
389+
crossThreadCopy(WTFMove(receiverStreamIds)),
390+
firedDirection
391+
};
392+
}
393+
394+
Vector<String> getMediaStreamIdsFromSDPMedia(const GstSDPMedia& media)
395+
{
396+
HashSet<String> mediaStreamIdsSet;
397+
for (guint i = 0; i < gst_sdp_media_attributes_len(&media); ++i) {
398+
const auto attribute = gst_sdp_media_get_attribute(&media, i);
399+
if (!g_strcmp0(attribute->key, "msid")) {
400+
auto components = String::fromUTF8(attribute->value).split(' ');
401+
if (components.size() < 2)
402+
continue;
403+
mediaStreamIdsSet.add(components[0]);
404+
}
405+
// MSID may also come in ssrc attributes, specially if they're in an SDP answer. They look like:
406+
// a=ssrc:3612593434 msid:e1019f4a-0983-4863-b923-b75903cced2c webrtctransceiver1
407+
if (!g_strcmp0(attribute->key, "ssrc")) {
408+
auto outerComponents = String::fromUTF8(attribute->value).split(' ');
409+
for (auto& outer : outerComponents) {
410+
auto innerComponents = outer.split(':');
411+
if (innerComponents.size() < 2)
412+
continue;
413+
if (innerComponents[0] == "msid"_s)
414+
mediaStreamIdsSet.add(innerComponents[1]);
415+
}
416+
}
417+
}
418+
Vector<String> mediaStreamIds;
419+
mediaStreamIds.reserveCapacity(mediaStreamIdsSet.size());
420+
for (const auto& msid : mediaStreamIdsSet)
421+
mediaStreamIds.append(msid);
422+
return mediaStreamIds;
423+
}
424+
425+
inline bool isRecvDirection(GstWebRTCRTPTransceiverDirection direction)
426+
{
427+
return direction == GST_WEBRTC_RTP_TRANSCEIVER_DIRECTION_SENDRECV || direction == GST_WEBRTC_RTP_TRANSCEIVER_DIRECTION_RECVONLY;
428+
}
429+
430+
static std::optional<GStreamerMediaEndpointTransceiverState> toGStreamerMediaEndpointTransceiverState(GstElement* webrtcBin, GstWebRTCRTPTransceiver* transceiver)
431+
{
432+
GRefPtr<GstWebRTCRTPReceiver> receiver;
433+
GUniqueOutPtr<char> mid;
434+
GstWebRTCRTPTransceiverDirection currentDirection;
435+
guint mLineIndex;
436+
g_object_get(transceiver, "receiver", &receiver.outPtr(), "current-direction", &currentDirection, "mlineindex", &mLineIndex, "mid", &mid.outPtr(), nullptr);
437+
#ifndef GST_DISABLE_GST_DEBUG
438+
GUniquePtr<char> desc(g_enum_to_string(GST_TYPE_WEBRTC_RTP_TRANSCEIVER_DIRECTION, currentDirection));
439+
GST_TRACE_OBJECT(webrtcBin, "Receiver = %" GST_PTR_FORMAT ", current-direction = %s, mlineindex = %u, mid = %s", receiver.get(), desc.get(), mLineIndex, GST_STR_NULL(mid.get()));
440+
#endif
441+
442+
GUniqueOutPtr<GstWebRTCSessionDescription> localDescription, remoteDescription;
443+
g_object_get(webrtcBin, "local-description", &localDescription.outPtr(), "remote-description", &remoteDescription.outPtr(), nullptr);
444+
445+
#ifndef GST_DISABLE_GST_DEBUG
446+
if (localDescription) {
447+
GUniquePtr<char> sdp(gst_sdp_message_as_text(localDescription->sdp));
448+
GST_TRACE_OBJECT(webrtcBin, "Local-description:\n%s", sdp.get());
449+
}
450+
if (remoteDescription) {
451+
GUniquePtr<char> sdp(gst_sdp_message_as_text(remoteDescription->sdp));
452+
GST_TRACE_OBJECT(webrtcBin, "Remote-description:\n%s", sdp.get());
453+
}
454+
#endif
455+
456+
Vector<String> streamIds;
457+
if (remoteDescription && remoteDescription->sdp && mLineIndex < gst_sdp_message_medias_len(remoteDescription->sdp)) {
458+
const GstSDPMedia* media = gst_sdp_message_get_media(remoteDescription->sdp, mLineIndex);
459+
if (isRecvDirection(currentDirection))
460+
streamIds = getMediaStreamIdsFromSDPMedia(*media);
461+
}
462+
463+
if (UNLIKELY(!mid))
464+
return { };
465+
466+
return { { String::fromUTF8(mid.get()), WTFMove(streamIds), { toRTCRtpTransceiverDirection(currentDirection) } } };
467+
}
468+
469+
static Vector<GStreamerMediaEndpointTransceiverState> transceiverStatesFromWebRTCBin(GstElement* webrtcBin)
470+
{
471+
Vector<GStreamerMediaEndpointTransceiverState> states;
472+
GRefPtr<GArray> transceivers;
473+
g_signal_emit_by_name(webrtcBin, "get-transceivers", &transceivers.outPtr());
474+
GST_TRACE_OBJECT(webrtcBin, "Filling transceiver states for %u transceivers", transceivers ? transceivers->len : 0);
475+
if (!transceivers || !transceivers->len)
476+
return states;
477+
478+
states.reserveInitialCapacity(transceivers->len);
479+
for (unsigned i = 0; i < transceivers->len; i++) {
480+
GstWebRTCRTPTransceiver* transceiver = g_array_index(transceivers.get(), GstWebRTCRTPTransceiver*, i);
481+
auto state = toGStreamerMediaEndpointTransceiverState(webrtcBin, transceiver);
482+
if (!state)
483+
continue;
484+
states.append(WTFMove(*state));
485+
}
486+
487+
return states;
488+
}
489+
373490
void GStreamerMediaEndpoint::doSetLocalDescription(const RTCSessionDescription* description)
374491
{
375492
RefPtr initialDescription = description;
@@ -458,6 +575,19 @@ void GStreamerMediaEndpoint::doSetLocalDescription(const RTCSessionDescription*
458575
}
459576
}
460577

578+
#ifndef GST_DISABLE_GST_DEBUG
579+
auto dotFileName = makeString(GST_OBJECT_NAME(m_pipeline.get()), ".setLocalDescription"_s);
580+
GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS(GST_BIN(m_pipeline.get()), GST_DEBUG_GRAPH_SHOW_ALL, dotFileName.utf8().data());
581+
#endif
582+
583+
auto rtcTransceiverStates = transceiverStatesFromWebRTCBin(m_webrtcBin.get());
584+
auto transceiverStates = WTF::map(rtcTransceiverStates, [this](auto& state) -> PeerConnectionBackend::TransceiverState {
585+
auto streams = WTF::map(state.receiverStreamIds, [this](auto& id) -> RefPtr<MediaStream> {
586+
return &mediaStreamFromRTCStream(id);
587+
});
588+
return { WTFMove(state.mid), WTFMove(streams), state.firedDirection };
589+
});
590+
461591
GRefPtr<GstWebRTCSCTPTransport> transport;
462592
g_object_get(m_webrtcBin.get(), "sctp-transport", &transport.outPtr(), nullptr);
463593

@@ -468,7 +598,7 @@ void GStreamerMediaEndpoint::doSetLocalDescription(const RTCSessionDescription*
468598
maxMessageSize = static_cast<double>(maxMessageSizeValue);
469599
}
470600

471-
m_peerConnectionBackend.setLocalDescriptionSucceeded(WTFMove(descriptions), { }, transport ? makeUnique<GStreamerSctpTransportBackend>(WTFMove(transport)) : nullptr, maxMessageSize);
601+
m_peerConnectionBackend.setLocalDescriptionSucceeded(WTFMove(descriptions), WTFMove(transceiverStates), transport ? makeUnique<GStreamerSctpTransportBackend>(WTFMove(transport)) : nullptr, maxMessageSize);
472602
}, [protectedThis = Ref(*this), this](const GError* error) {
473603
if (protectedThis->isStopped())
474604
return;
@@ -483,6 +613,22 @@ void GStreamerMediaEndpoint::doSetLocalDescription(const RTCSessionDescription*
483613
});
484614
}
485615

616+
void GStreamerMediaEndpoint::setTransceiverCodecPreferences(const GstSDPMedia& media, guint transceiverIdx)
617+
{
618+
auto direction = getDirectionFromSDPMedia(&media);
619+
if (direction == GST_WEBRTC_RTP_TRANSCEIVER_DIRECTION_NONE)
620+
return;
621+
622+
GRefPtr<GstWebRTCRTPTransceiver> rtcTransceiver;
623+
g_signal_emit_by_name(m_webrtcBin.get(), "get-transceiver", transceiverIdx, &rtcTransceiver.outPtr());
624+
if (!rtcTransceiver)
625+
return;
626+
627+
auto caps = capsFromSDPMedia(&media);
628+
GST_TRACE_OBJECT(m_webrtcBin.get(), "Setting codec-preferences to %" GST_PTR_FORMAT, caps.get());
629+
g_object_set(rtcTransceiver.get(), "codec-preferences", caps.get(), nullptr);
630+
}
631+
486632
void GStreamerMediaEndpoint::doSetRemoteDescription(const RTCSessionDescription& description)
487633
{
488634
auto initialSDP = description.sdp().isolatedCopy();
@@ -494,17 +640,9 @@ void GStreamerMediaEndpoint::doSetRemoteDescription(const RTCSessionDescription&
494640
unsigned numberOfMedias = gst_sdp_message_medias_len(&message);
495641
for (unsigned i = 0; i < numberOfMedias; i++) {
496642
const auto* media = gst_sdp_message_get_media(&message, i);
497-
auto direction = getDirectionFromSDPMedia(media);
498-
if (direction == GST_WEBRTC_RTP_TRANSCEIVER_DIRECTION_NONE)
643+
if (UNLIKELY(!media))
499644
continue;
500-
501-
GRefPtr<GstWebRTCRTPTransceiver> rtcTransceiver;
502-
g_signal_emit_by_name(m_webrtcBin.get(), "get-transceiver", i, &rtcTransceiver.outPtr());
503-
if (!rtcTransceiver)
504-
continue;
505-
506-
auto caps = capsFromSDPMedia(media);
507-
g_object_set(rtcTransceiver.get(), "codec-preferences", caps.get(), nullptr);
645+
setTransceiverCodecPreferences(*media, i);
508646
}
509647
}, [protectedThis = Ref(*this), this, initialSDP = WTFMove(initialSDP), localDescriptionSdp = WTFMove(localDescriptionSdp), localDescriptionSdpType = WTFMove(localDescriptionSdpType)](const GstSDPMessage& message) {
510648
if (protectedThis->isStopped())
@@ -540,6 +678,19 @@ void GStreamerMediaEndpoint::doSetRemoteDescription(const RTCSessionDescription&
540678
}
541679
}
542680

681+
#ifndef GST_DISABLE_GST_DEBUG
682+
auto dotFileName = makeString(GST_OBJECT_NAME(m_pipeline.get()), ".setRemoteDescription"_s);
683+
GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS(GST_BIN(m_pipeline.get()), GST_DEBUG_GRAPH_SHOW_ALL, dotFileName.utf8().data());
684+
#endif
685+
686+
auto rtcTransceiverStates = transceiverStatesFromWebRTCBin(m_webrtcBin.get());
687+
auto transceiverStates = WTF::map(rtcTransceiverStates, [this](auto& state) -> PeerConnectionBackend::TransceiverState {
688+
auto streams = WTF::map(state.receiverStreamIds, [this](auto& id) -> RefPtr<MediaStream> {
689+
return &mediaStreamFromRTCStream(id);
690+
});
691+
return { WTFMove(state.mid), WTFMove(streams), state.firedDirection };
692+
});
693+
543694
GRefPtr<GstWebRTCSCTPTransport> transport;
544695
g_object_get(m_webrtcBin.get(), "sctp-transport", &transport.outPtr(), nullptr);
545696

@@ -550,7 +701,7 @@ void GStreamerMediaEndpoint::doSetRemoteDescription(const RTCSessionDescription&
550701
maxMessageSize = static_cast<double>(maxMessageSizeValue);
551702
}
552703

553-
m_peerConnectionBackend.setRemoteDescriptionSucceeded(WTFMove(descriptions), { }, transport ? makeUnique<GStreamerSctpTransportBackend>(WTFMove(transport)) : nullptr, maxMessageSize);
704+
m_peerConnectionBackend.setRemoteDescriptionSucceeded(WTFMove(descriptions), WTFMove(transceiverStates), transport ? makeUnique<GStreamerSctpTransportBackend>(WTFMove(transport)) : nullptr, maxMessageSize);
554705
}, [protectedThis = Ref(*this), this](const GError* error) {
555706
if (protectedThis->isStopped())
556707
return;
@@ -576,6 +727,8 @@ WEBKIT_DEFINE_ASYNC_DATA_STRUCT(SetDescriptionCallData)
576727

577728
void GStreamerMediaEndpoint::setDescription(const RTCSessionDescription* description, DescriptionType descriptionType, Function<void(const GstSDPMessage&)>&& preProcessCallback, Function<void(const GstSDPMessage&)>&& successCallback, Function<void(const GError*)>&& failureCallback)
578729
{
730+
GST_DEBUG_OBJECT(m_webrtcBin.get(), "Setting %s description", descriptionType == DescriptionType::Local ? "local" : "remote");
731+
579732
GUniqueOutPtr<GstSDPMessage> message;
580733
auto sdpType = RTCSdpType::Offer;
581734

@@ -990,12 +1143,9 @@ void GStreamerMediaEndpoint::connectIncomingTrack(WebRTCTrackData& data)
9901143
GST_WARNING_OBJECT(m_pipeline.get(), "SDP media for transceiver %u not found, skipping incoming track setup", mLineIndex);
9911144
return;
9921145
}
993-
9941146
transceiver = &m_peerConnectionBackend.newRemoteTransceiver(makeUnique<GStreamerRtpTransceiverBackend>(WTFMove(rtcTransceiver)), data.type, trackIdFromSDPMedia(*media));
9951147
}
9961148

997-
m_peerConnectionBackend.addPendingTrackEvent({ Ref(transceiver->receiver()), Ref(transceiver->receiver().track()), { }, Ref(*transceiver) });
998-
9991149
auto mediaStreamBin = adoptGRef(gst_bin_get_by_name(GST_BIN_CAST(m_pipeline.get()), data.mediaStreamBinName.ascii().data()));
10001150
auto& track = transceiver->receiver().track();
10011151
auto& source = track.privateTrack().source();
@@ -1009,22 +1159,32 @@ void GStreamerMediaEndpoint::connectIncomingTrack(WebRTCTrackData& data)
10091159
return;
10101160
}
10111161

1012-
auto& mediaStream = mediaStreamFromRTCStream(data.mediaStreamId);
1013-
mediaStream.addTrackFromPlatform(track);
1162+
m_pendingIncomingMediaStreamIDs.append(data.mediaStreamId);
10141163

1015-
for (auto& processor : m_trackProcessors.values()) {
1016-
if (!processor->isReady())
1017-
return;
1164+
unsigned totalExpectedMediaTracks = 0;
1165+
for (unsigned i = 0; i < gst_sdp_message_medias_len(description->sdp); i++) {
1166+
const auto media = gst_sdp_message_get_media(description->sdp, i);
1167+
const char* mediaType = gst_sdp_media_get_media(media);
1168+
if (g_str_equal(mediaType, "audio") || g_str_equal(mediaType, "video"))
1169+
totalExpectedMediaTracks++;
10181170
}
10191171

1020-
GST_DEBUG_OBJECT(m_pipeline.get(), "Incoming streams gathered, now dispatching track events");
1021-
m_peerConnectionBackend.dispatchPendingTrackEvents(mediaStream);
1022-
gst_element_set_state(m_pipeline.get(), GST_STATE_PLAYING);
1172+
GST_DEBUG_OBJECT(m_pipeline.get(), "Expecting %u media tracks", totalExpectedMediaTracks);
1173+
if (m_pendingIncomingMediaStreamIDs.size() < totalExpectedMediaTracks) {
1174+
GST_DEBUG_OBJECT(m_pipeline.get(), "Only %zu track(s) received so far", m_pendingIncomingMediaStreamIDs.size());
1175+
return;
1176+
}
10231177

1024-
#ifndef GST_DISABLE_GST_DEBUG
1025-
auto dotFileName = makeString(GST_OBJECT_NAME(m_pipeline.get()), ".connected-"_s, data.mediaStreamId);
1026-
GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS(GST_BIN(m_pipeline.get()), GST_DEBUG_GRAPH_SHOW_ALL, dotFileName.utf8().data());
1027-
#endif
1178+
for (auto& mediaStreamID : m_pendingIncomingMediaStreamIDs) {
1179+
auto& mediaStream = mediaStreamFromRTCStream(mediaStreamID);
1180+
GST_DEBUG_OBJECT(m_pipeline.get(), "Incoming stream %s ready, notifying observers", mediaStreamID.ascii().data());
1181+
mediaStream.privateStream().forEachTrack([](auto& track) {
1182+
GST_DEBUG("Incoming stream has track %s", track.id().ascii().data());
1183+
track.dataFlowStarted();
1184+
});
1185+
}
1186+
1187+
m_pendingIncomingMediaStreamIDs.clear();
10281188
gst_element_set_state(m_pipeline.get(), GST_STATE_PLAYING);
10291189
}
10301190

0 commit comments

Comments
 (0)