This commit is contained in:
Tobias Fella
2023-06-13 23:32:57 +02:00
parent 12bb75e5b0
commit 39ee17cfa1
5 changed files with 42 additions and 38 deletions

View File

@@ -203,8 +203,9 @@ void CallManager::handleNegotiate(NeoChatRoom *room, const Quotient::CallNegotia
qCDebug(voip) << "Ignoring negotiate for unknown user id" << event->senderId() << ". Remote user id is" << m_remoteUser->id(); qCDebug(voip) << "Ignoring negotiate for unknown user id" << event->senderId() << ". Remote user id is" << m_remoteUser->id();
return; return;
} }
// TODO DUPLICATES FFS
m_session->setMetadata(event->contentJson()["org.matrix.msc3077.sdp_stream_metadata"].toObject()); m_session->setMetadata(event->contentJson()["org.matrix.msc3077.sdp_stream_metadata"].toObject());
m_session->renegotiateOffer(event->sdp(), m_remoteUser->id()); m_session->renegotiateOffer(event->sdp(), m_remoteUser->id(), event->contentJson()["description"]["type"] == QStringLiteral("answer"));
} }
void CallManager::ring(int lifetime) void CallManager::ring(int lifetime)
@@ -406,7 +407,7 @@ void CallManager::startCall(NeoChatRoom *room)
m_room->postJson("m.call.candidates", c); m_room->postJson("m.call.candidates", c);
}); });
connect(m_session, &CallSession::renegotiate, this, [this](const QString &sdp) { connect(m_session, &CallSession::renegotiate, this, [this](const QString &sdp, const QString &type) {
QVector<std::pair<QString, QString>> msidToPurpose; QVector<std::pair<QString, QString>> msidToPurpose;
const auto &[uuids, _sdp] = mangleSdp(sdp); const auto &[uuids, _sdp] = mangleSdp(sdp);
for (const auto &uuid : uuids) { for (const auto &uuid : uuids) {
@@ -415,7 +416,7 @@ void CallManager::startCall(NeoChatRoom *room)
QJsonObject json{ QJsonObject json{
{QStringLiteral("lifetime"), 60000}, {QStringLiteral("lifetime"), 60000},
{QStringLiteral("version"), 1}, {QStringLiteral("version"), 1},
{QStringLiteral("description"), QJsonObject{{QStringLiteral("type"), QStringLiteral("answer")}, {QStringLiteral("sdp"), _sdp}}}, {QStringLiteral("description"), QJsonObject{{QStringLiteral("type"), type}, {QStringLiteral("sdp"), _sdp}}}, // AAAAA
{QStringLiteral("party_id"), m_partyId}, {QStringLiteral("party_id"), m_partyId},
{QStringLiteral("call_id"), m_callId}, {QStringLiteral("call_id"), m_callId},
}; };
@@ -425,6 +426,7 @@ void CallManager::startCall(NeoChatRoom *room)
metadata[stream] = purpose; metadata[stream] = purpose;
} }
json["org.matrix.msc3077.sdp_stream_metadata"] = metadata; json["org.matrix.msc3077.sdp_stream_metadata"] = metadata;
qWarning() << json;
m_room->postJson("m.call.negotiate", json); m_room->postJson("m.call.negotiate", json);
}); });
} }

View File

@@ -84,6 +84,7 @@ void setLocalDescription(GstPromise *promise, gpointer user_data)
{ {
INSTANCE INSTANCE
qCDebug(voip) << "Setting local description"; qCDebug(voip) << "Setting local description";
qWarning() << "SETTING LOCAL DESCRIPTION";
const GstStructure *reply = gst_promise_get_reply(promise); const GstStructure *reply = gst_promise_get_reply(promise);
gboolean isAnswer = gst_structure_id_has_field(reply, g_quark_from_string("answer")); gboolean isAnswer = gst_structure_id_has_field(reply, g_quark_from_string("answer"));
GstWebRTCSessionDescription *gstsdp = nullptr; GstWebRTCSessionDescription *gstsdp = nullptr;
@@ -95,7 +96,8 @@ void setLocalDescription(GstPromise *promise, gpointer user_data)
gchar *sdp = gst_sdp_message_as_text(gstsdp->sdp); gchar *sdp = gst_sdp_message_as_text(gstsdp->sdp);
if (!instance->m_localSdp.isEmpty()) { if (!instance->m_localSdp.isEmpty()) {
// This is a renegotiation // This is a renegotiation
Q_EMIT instance->renegotiate(QString(sdp)); qWarning() << "emitting renegotiate";
Q_EMIT instance->renegotiate(QString(sdp), isAnswer ? QStringLiteral("answer") : QStringLiteral("offer"));
} }
instance->m_localSdp = QString(sdp); instance->m_localSdp = QString(sdp);
g_free(sdp); g_free(sdp);
@@ -195,9 +197,10 @@ void iceConnectionStateChanged(GstElement *webrtc, GParamSpec *pspec, gpointer u
case GST_WEBRTC_ICE_CONNECTION_STATE_FAILED: case GST_WEBRTC_ICE_CONNECTION_STATE_FAILED:
instance->setState(CallSession::ICEFAILED); instance->setState(CallSession::ICEFAILED);
break; break;
case GST_WEBRTC_ICE_CONNECTION_STATE_CONNECTED:
instance->setState(CallSession::CONNECTED);
case GST_WEBRTC_ICE_CONNECTION_STATE_COMPLETED: case GST_WEBRTC_ICE_CONNECTION_STATE_COMPLETED:
case GST_WEBRTC_ICE_CONNECTION_STATE_DISCONNECTED: case GST_WEBRTC_ICE_CONNECTION_STATE_DISCONNECTED:
case GST_WEBRTC_ICE_CONNECTION_STATE_CONNECTED:
case GST_WEBRTC_ICE_CONNECTION_STATE_CLOSED: case GST_WEBRTC_ICE_CONNECTION_STATE_CLOSED:
default: default:
break; break;
@@ -263,6 +266,8 @@ gboolean testPacketLoss(gpointer)
GstElement *newVideoSinkChain(GstElement *pipe, QQuickItem *quickItem) GstElement *newVideoSinkChain(GstElement *pipe, QQuickItem *quickItem)
{ {
Q_ASSERT(pipe);
Q_ASSERT(quickItem);
qCWarning(voip) << "Creating Video Sink Chain"; qCWarning(voip) << "Creating Video Sink Chain";
auto queue = createElement("queue", pipe); auto queue = createElement("queue", pipe);
auto compositor = createElement("compositor", pipe); auto compositor = createElement("compositor", pipe);
@@ -496,17 +501,20 @@ void CallSession::setRemoteDescription(GstWebRTCSessionDescription *remote, cons
g_signal_emit_by_name(webrtcbin, "set-remote-description", remote, promise); g_signal_emit_by_name(webrtcbin, "set-remote-description", remote, promise);
} }
void CallSession::renegotiateOffer(const QString &_offer, const QString &userId) void CallSession::renegotiateOffer(const QString &_offer, const QString &userId, bool answer)
{ {
GstWebRTCSessionDescription *offer = parseSDP(_offer, GST_WEBRTC_SDP_TYPE_OFFER); GstWebRTCSessionDescription *sdp = parseSDP(_offer, answer ? GST_WEBRTC_SDP_TYPE_ANSWER : GST_WEBRTC_SDP_TYPE_OFFER);
if (!offer) { if (!sdp) {
Q_ASSERT(false); Q_ASSERT(false);
} }
GstElement *webrtcbin = binGetByName(m_pipe, "webrtcbin"); GstElement *webrtcbin = binGetByName(m_pipe, "webrtcbin");
setRemoteDescription(offer, userId); setRemoteDescription(sdp, userId);
GstPromise *promise = gst_promise_new_with_change_func(setLocalDescription, this, nullptr); qWarning() << "answer:" << answer;
g_signal_emit_by_name(webrtcbin, "create-answer", nullptr, promise); if (!answer) {
GstPromise *promise = gst_promise_new_with_change_func(setLocalDescription, this, nullptr);
g_signal_emit_by_name(webrtcbin, "create-answer", nullptr, promise);
}
} }
void CallSession::acceptOffer(const QString &sdp, const QVector<Candidate> remoteCandidates, const QString &userId) void CallSession::acceptOffer(const QString &sdp, const QVector<Candidate> remoteCandidates, const QString &userId)
@@ -676,18 +684,16 @@ void CallSession::createPipeline()
// TODO propagate errors up and end call // TODO propagate errors up and end call
return; return;
} }
// if (sendVideo) {
// TODO where? addVideoPipeline();
// }
} }
void CallSession::toggleCamera() void CallSession::toggleCamera()
{ {
g_object_set(m_inputSelector, "active-pad", m_inactivePad, nullptr); // TODO do this only once
auto _tmp = m_inactivePad; static bool inited = false;
m_inactivePad = m_activePad; if (!inited) {
m_activePad = _tmp; addVideoPipeline();
inited = true;
}
} }
bool CallSession::addVideoPipeline() bool CallSession::addVideoPipeline()
@@ -712,19 +718,7 @@ bool CallSession::addVideoPipeline()
g_object_set(camerafilter, "caps", caps, nullptr); g_object_set(camerafilter, "caps", caps, nullptr);
gst_caps_unref(caps); gst_caps_unref(caps);
auto videotestsrc = createElement("videotestsrc", m_pipe); gst_element_link(camera, videoconvert);
m_inputSelector = createElement("input-selector", m_pipe);
g_object_set(m_inputSelector, "sync-mode", 1, nullptr);
m_inactivePad = gst_element_request_pad_simple(m_inputSelector, "sink_%u");
gst_pad_link(gst_element_get_static_pad(videotestsrc, "src"), m_inactivePad);
auto selectorSrc = gst_element_get_static_pad(m_inputSelector, "src");
gst_pad_link(selectorSrc, gst_element_get_static_pad(videoconvert, "sink"));
m_activePad = gst_element_request_pad_simple(m_inputSelector, "sink_%u");
gst_pad_link(gst_element_get_static_pad(camera, "src"), m_activePad);
g_object_set(m_inputSelector, "active-pad", m_activePad, nullptr);
if (!gst_element_link_many(videoconvert, camerafilter, nullptr)) { if (!gst_element_link_many(videoconvert, camerafilter, nullptr)) {
qCWarning(voip) << "Failed to link camera elements"; qCWarning(voip) << "Failed to link camera elements";
@@ -765,6 +759,8 @@ bool CallSession::addVideoPipeline()
gst_object_unref(webrtcbin); gst_object_unref(webrtcbin);
return false; return false;
} }
auto promise = gst_promise_new_with_change_func(setLocalDescription, this, nullptr);
g_signal_emit_by_name(webrtcbin, "create-offer", nullptr, promise);
gst_object_unref(webrtcbin); gst_object_unref(webrtcbin);
@@ -790,6 +786,7 @@ bool CallSession::addVideoPipeline()
connectSingleShot(participant, &CallParticipant::initialized, this, [=](QQuickItem *item) { connectSingleShot(participant, &CallParticipant::initialized, this, [=](QQuickItem *item) {
gst_pad_unlink(newpad, fakepad); gst_pad_unlink(newpad, fakepad);
Q_ASSERT(item);
auto queue = newVideoSinkChain(m_pipe, item); auto queue = newVideoSinkChain(m_pipe, item);
Q_ASSERT(queue); Q_ASSERT(queue);
@@ -801,6 +798,7 @@ bool CallSession::addVideoPipeline()
Q_ASSERT(ok); Q_ASSERT(ok);
g_object_set(selector, "active-pad", selectorSrc, nullptr); g_object_set(selector, "active-pad", selectorSrc, nullptr);
gst_object_unref(queuepad); gst_object_unref(queuepad);
GST_DEBUG_BIN_TO_DOT_FILE(GST_BIN(m_pipe), GST_DEBUG_GRAPH_SHOW_ALL, "foo");
}); });
return true; return true;
} }

View File

@@ -62,7 +62,7 @@ public:
void end(); void end();
void renegotiateOffer(const QString &offer, const QString &userId); void renegotiateOffer(const QString &offer, const QString &userId, bool answer);
void setTurnServers(QStringList servers); void setTurnServers(QStringList servers);
static QStringList missingPlugins(); static QStringList missingPlugins();
@@ -85,7 +85,7 @@ Q_SIGNALS:
void mutedChanged(); void mutedChanged();
void newVideoStream(VideoStream *stream); void newVideoStream(VideoStream *stream);
void renegotiate(QString sdp); void renegotiate(QString sdp, const QString &type);
private: private:
CallSession(QObject *parent = nullptr); CallSession(QObject *parent = nullptr);

View File

@@ -34,7 +34,11 @@ Rectangle {
Layout.preferredHeight: parent.height Layout.preferredHeight: parent.height
Layout.preferredWidth: parent.width Layout.preferredWidth: parent.width
Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
onActiveChanged: if (active) model.object.initCamera(camera) onActiveChanged: {
if (active) {
model.object.initCamera(camera)
}
}
Component.onCompleted: if (active) model.object.initCamera(camera) Component.onCompleted: if (active) model.object.initCamera(camera)
GstGLVideoItem { GstGLVideoItem {
id: camera id: camera
@@ -55,7 +59,7 @@ Rectangle {
height: parent.height height: parent.height
Component.onCompleted: { Component.onCompleted: {
//model.object.initCamera(this) model.object.initCamera(this)
} }
} }
} }

View File

@@ -84,8 +84,8 @@ Kirigami.Page {
} }
} }
CallPageButton { CallPageButton {
text: checked ? i18n("Enable Camera") : i18n("Disable Camera") text: checked ? i18n("Disable Camera") : i18n("Enable Camera")
icon.name: checked ? "camera-off" : "camera-on" icon.name: checked ? "camera-on" : "camera-off"
checkable: true checkable: true
onToggled: CallManager.toggleCamera() onToggled: CallManager.toggleCamera()
} }