?
This commit is contained in:
@@ -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);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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()
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user