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();
return;
}
// TODO DUPLICATES FFS
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)
@@ -406,7 +407,7 @@ void CallManager::startCall(NeoChatRoom *room)
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;
const auto &[uuids, _sdp] = mangleSdp(sdp);
for (const auto &uuid : uuids) {
@@ -415,7 +416,7 @@ void CallManager::startCall(NeoChatRoom *room)
QJsonObject json{
{QStringLiteral("lifetime"), 60000},
{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("call_id"), m_callId},
};
@@ -425,6 +426,7 @@ void CallManager::startCall(NeoChatRoom *room)
metadata[stream] = purpose;
}
json["org.matrix.msc3077.sdp_stream_metadata"] = metadata;
qWarning() << json;
m_room->postJson("m.call.negotiate", json);
});
}

View File

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

View File

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

View File

@@ -34,7 +34,11 @@ Rectangle {
Layout.preferredHeight: parent.height
Layout.preferredWidth: parent.width
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)
GstGLVideoItem {
id: camera
@@ -55,7 +59,7 @@ Rectangle {
height: parent.height
Component.onCompleted: {
//model.object.initCamera(this)
model.object.initCamera(this)
}
}
}

View File

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