diff --git a/src/api/call.h b/src/api/call.h
index d7a2da2bfadc5d2f292a82aff492416865101f4b..922449ce8d0228f1d6901025c2c6061e535c801c 100644
--- a/src/api/call.h
+++ b/src/api/call.h
@@ -138,6 +138,7 @@ struct Info
     bool isAudioOnly = false;
     Layout layout = Layout::GRID;
     VectorMapStringString participantsInfos = {};
+    VectorMapStringString mediaList = {};
     QSet<QString> peerRec {};
 };
 
diff --git a/src/api/newcallmodel.h b/src/api/newcallmodel.h
index 8c5c3d8113ed3264a4989f55f4056b69adc78d4f..124b77af092e92f40ecd8653a05b1ee41b61cfab 100644
--- a/src/api/newcallmodel.h
+++ b/src/api/newcallmodel.h
@@ -234,6 +234,14 @@ public:
      */
     void setCurrentCall(const QString& callId) const;
 
+    /**
+     * Update call mediaList to be used in the call answering
+     *
+     * @param callId
+     * @param acceptVideo
+     */
+    void updateCallMediaList(const QString& callId, bool acceptVideo);
+
     /**
      * Change the conference layout
      */
diff --git a/src/callbackshandler.cpp b/src/callbackshandler.cpp
index 54777d5b20420259e12707b66fb84ae436f4a257..419800d7e5b495d401263c6b7455f6e887245e8d 100644
--- a/src/callbackshandler.cpp
+++ b/src/callbackshandler.cpp
@@ -120,6 +120,12 @@ CallbacksHandler::CallbacksHandler(const Lrc& parent)
             &CallbacksHandler::slotIncomingCall,
             Qt::QueuedConnection);
 
+    connect(&CallManager::instance(),
+            &CallManagerInterface::incomingCallWithMedia,
+            this,
+            &CallbacksHandler::slotIncomingCallWithMedia,
+            Qt::QueuedConnection);
+
     connect(&CallManager::instance(),
             &CallManagerInterface::callStateChanged,
             this,
@@ -333,6 +339,15 @@ void
 CallbacksHandler::slotIncomingCall(const QString& accountId,
                                    const QString& callId,
                                    const QString& fromUri)
+{
+    slotIncomingCallWithMedia(accountId, callId, fromUri, {});
+}
+
+void
+CallbacksHandler::slotIncomingCallWithMedia(const QString& accountId,
+                                            const QString& callId,
+                                            const QString& fromUri,
+                                            const VectorMapStringString& mediaList)
 {
     QString displayname;
     QString fromQString;
@@ -349,7 +364,7 @@ CallbacksHandler::slotIncomingCall(const QString& accountId,
         fromQString = fromUri.mid(left, right - left);
         displayname = fromUri.left(fromUri.indexOf("<") - 1);
     }
-    emit incomingCall(accountId, callId, fromQString, displayname);
+    emit incomingCallWithMedia(accountId, callId, fromQString, displayname, mediaList);
 }
 
 void
diff --git a/src/callbackshandler.h b/src/callbackshandler.h
index 90de27d2ac21f8e08e7c252d7fdbd57e919e6ea4..e06be5ab47f5992730c8be2a8dad713f3d986182 100644
--- a/src/callbackshandler.h
+++ b/src/callbackshandler.h
@@ -105,11 +105,13 @@ Q_SIGNALS:
      * @param callId the call id
      * @param fromUri the caller uri
      * @param displayName the display name of incoming call
+     * @param mediaList media received
      */
-    void incomingCall(const QString& accountId,
-                      const QString& callId,
-                      const QString& fromUri,
-                      const QString& displayName);
+    void incomingCallWithMedia(const QString& accountId,
+                               const QString& callId,
+                               const QString& fromUri,
+                               const QString& displayName,
+                               const VectorMapStringString& mediaList);
     /**
      * Connect this signal to know when a call is updated
      * @param callId the call id
@@ -390,12 +392,24 @@ private Q_SLOTS:
                                       unsigned detail_code,
                                       const QString& detail_str);
     /**
+     * @deprecated Use slotIncomingCallWithMedia instead
      * Get the URI of the peer and emit incomingCall
      * @param accountId account linked
      * @param callId the incoming call id
      * @param fromQString the uri of the peer
      */
     void slotIncomingCall(const QString& accountId, const QString& callId, const QString& fromUri);
+    /**
+     * Get the URI of the peer and emit incomingCallWithMedia
+     * @param accountId account linked
+     * @param callId the incoming call id
+     * @param fromQString the uri of the peer
+     * @param mediaList the mediaList received
+     */
+    void slotIncomingCallWithMedia(const QString& accountId,
+                                   const QString& callId,
+                                   const QString& fromUri,
+                                   const VectorMapStringString& mediaList);
     /**
      * Emit callStateChanged
      * @param callId the call which changes.
diff --git a/src/newcallmodel.cpp b/src/newcallmodel.cpp
index 44b168836b63ad86d2aa584c1961104e14579d35..e7c4e3a2e9fbc71c09a98cc0e796245d79b9bd90 100644
--- a/src/newcallmodel.cpp
+++ b/src/newcallmodel.cpp
@@ -157,11 +157,13 @@ public Q_SLOTS:
      * @param callId
      * @param fromId peer uri
      * @param displayname
+     * @param mediaList media received
      */
-    void slotIncomingCall(const QString& accountId,
-                          const QString& callId,
-                          const QString& fromId,
-                          const QString& displayname);
+    void slotIncomingCallWithMedia(const QString& accountId,
+                                   const QString& callId,
+                                   const QString& fromId,
+                                   const QString& displayname,
+                                   const VectorMapStringString& mediaList);
     /**
      * Listen from CallbacksHandler when a call got a new state
      * @param callId
@@ -263,20 +265,46 @@ NewCallModel::getCall(const QString& uid) const
     return *pimpl_->calls.at(uid);
 }
 
+void
+NewCallModel::updateCallMediaList(const QString& callId, bool acceptVideo)
+{
+    try {
+        auto callInfos = pimpl_->calls.find(callId);
+        if (callInfos != pimpl_->calls.end()) {
+            for (auto it = callInfos->second->mediaList.begin();
+                 it != callInfos->second->mediaList.end();
+                 it++) {
+                if ((*it)["MEDIA_TYPE"] == "MEDIA_TYPE_VIDEO" && !acceptVideo) {
+                    (*it)["ENABLED"] = "true";
+                    (*it)["MUTED"] = "true";
+                    callInfos->second->videoMuted = !acceptVideo;
+                }
+            }
+        }
+    } catch (...) {
+    }
+}
+
 QString
 NewCallModel::createCall(const QString& uri, bool isAudioOnly)
 {
+    VectorMapStringString mediaList {};
+    MapStringString mediaAttribute = {{"MEDIA_TYPE", "MEDIA_TYPE_AUDIO"},
+                                      {"ENABLED", "true"},
+                                      {"MUTED", "false"},
+                                      {"SOURCE", ""},
+                                      {"LABEL", "main_audio"}};
+    mediaList.push_back(mediaAttribute);
+    if (!isAudioOnly) {
+        mediaAttribute["MEDIA_TYPE"] = "MEDIA_TYPE_VIDEO";
+        mediaAttribute["LABEL"] = "main_video";
+        mediaList.push_back(mediaAttribute);
+    }
 #ifdef ENABLE_LIBWRAP
-    auto callId = isAudioOnly
-                      ? CallManager::instance().placeCall(owner.id, uri, {{"AUDIO_ONLY", "true"}})
-                      : CallManager::instance().placeCall(owner.id, uri);
-#else // dbus
+    auto callId = CallManager::instance().placeCallWithMedia(owner.id, uri, mediaList);
+#else  // dbus
     // do not use auto here (QDBusPendingReply<QString>)
-    QString callId = isAudioOnly
-                         ? CallManager::instance().placeCallWithDetails(owner.id,
-                                                                        uri,
-                                                                        {{"AUDIO_ONLY", "true"}})
-                         : CallManager::instance().placeCall(owner.id, uri);
+    QString callId = CallManager::instance().placeCallWithMedia(owner.id, uri, mediaList);
 #endif // ENABLE_LIBWRAP
 
     if (callId.isEmpty()) {
@@ -291,6 +319,7 @@ NewCallModel::createCall(const QString& uri, bool isAudioOnly)
     callInfo->status = call::Status::SEARCHING;
     callInfo->type = call::Type::DIALOG;
     callInfo->isAudioOnly = isAudioOnly;
+    callInfo->mediaList = mediaList;
     pimpl_->calls.emplace(callId, std::move(callInfo));
 
     return callId;
@@ -299,7 +328,16 @@ NewCallModel::createCall(const QString& uri, bool isAudioOnly)
 void
 NewCallModel::accept(const QString& callId) const
 {
-    CallManager::instance().accept(callId);
+    try {
+        auto& callInfo = pimpl_->calls[callId];
+        if (!callInfo)
+            return;
+        if (callInfo->mediaList.empty())
+            CallManager::instance().accept(callId);
+        else
+            CallManager::instance().acceptWithMedia(callId, callInfo->mediaList);
+    } catch (...) {
+    }
 }
 
 void
@@ -571,9 +609,9 @@ NewCallModelPimpl::NewCallModelPimpl(const NewCallModel& linked,
     , behaviorController(behaviorController)
 {
     connect(&callbacksHandler,
-            &CallbacksHandler::incomingCall,
+            &CallbacksHandler::incomingCallWithMedia,
             this,
-            &NewCallModelPimpl::slotIncomingCall);
+            &NewCallModelPimpl::slotIncomingCallWithMedia);
     connect(&callbacksHandler,
             &CallbacksHandler::callStateChanged,
             this,
@@ -845,10 +883,11 @@ NewCallModel::isConferenceHost(const QString& callId)
 }
 
 void
-NewCallModelPimpl::slotIncomingCall(const QString& accountId,
-                                    const QString& callId,
-                                    const QString& fromId,
-                                    const QString& displayname)
+NewCallModelPimpl::slotIncomingCallWithMedia(const QString& accountId,
+                                             const QString& callId,
+                                             const QString& fromId,
+                                             const QString& displayname,
+                                             const VectorMapStringString& mediaList)
 {
     if (linked.owner.id != accountId) {
         return;
@@ -874,6 +913,7 @@ NewCallModelPimpl::slotIncomingCall(const QString& accountId,
     callInfo->status = call::Status::INCOMING_RINGING;
     callInfo->type = call::Type::DIALOG;
     callInfo->isAudioOnly = callDetails["AUDIO_ONLY"] == "true" ? true : false;
+    callInfo->mediaList = mediaList;
     calls.emplace(callId, std::move(callInfo));
 
     if (!linked.owner.confProperties.allowIncoming
@@ -885,7 +925,7 @@ NewCallModelPimpl::slotIncomingCall(const QString& accountId,
     emit linked.newIncomingCall(fromId, callId, displayname);
 
     // HACK. BECAUSE THE DAEMON DOESN'T HANDLE THIS CASE!
-    if (linked.owner.confProperties.autoAnswer) {
+    if (!linked.owner.confProperties.isRendezVous && linked.owner.confProperties.autoAnswer) {
         linked.accept(callId);
     }
 }
diff --git a/src/qtwrapper/callmanager_wrap.h b/src/qtwrapper/callmanager_wrap.h
index 1de7a7fa7ee0e7d2a41ac33327b104e7d70332b3..e2ac06831c5d55067b11905242982db364bc72da 100644
--- a/src/qtwrapper/callmanager_wrap.h
+++ b/src/qtwrapper/callmanager_wrap.h
@@ -103,6 +103,21 @@ public:
                                     QString(callID.c_str()),
                                     QString(from.c_str()));
             }),
+            exportable_callback<CallSignal::IncomingCallWithMedia>(
+                [this](const std::string& accountID,
+                       const std::string& callID,
+                       const std::string& from,
+                       const std::vector<std::map<std::string, std::string>>& mediaList) {
+                    LOG_DRING_SIGNAL4("incomingCallWithMedia",
+                                      QString(accountID.c_str()),
+                                      QString(callID.c_str()),
+                                      QString(from.c_str()),
+                                      convertVecMap(mediaList));
+                    Q_EMIT incomingCallWithMedia(QString(accountID.c_str()),
+                                                 QString(callID.c_str()),
+                                                 QString(from.c_str()),
+                                                 convertVecMap(mediaList));
+                }),
             exportable_callback<CallSignal::RecordPlaybackFilepath>(
                 [this](const std::string& callID, const std::string& filepath) {
                     LOG_DRING_SIGNAL2("recordPlaybackFilepath",
@@ -172,9 +187,7 @@ public:
                     Q_EMIT smartInfo(convertMap(info));
                 }),
             exportable_callback<CallSignal::RemoteRecordingChanged>(
-                [this](const std::string &callID,
-                       const std::string &contactId,
-                       bool state) {
+                [this](const std::string& callID, const std::string& contactId, bool state) {
                     LOG_DRING_SIGNAL3("remoteRecordingChanged",
                                       QString(callID.c_str()),
                                       QString(contactId.c_str()),
@@ -315,6 +328,34 @@ public Q_SLOTS: // METHODS
         return temp;
     }
 
+    // MULTISTREAM FUNCTIONS
+    QString placeCallWithMedia(const QString& accountID,
+                               const QString& to,
+                               const VectorMapStringString& mediaList)
+    {
+        QString temp(DRing::placeCallWithMedia(accountID.toStdString(),
+                                               to.toStdString(),
+                                               convertVecMap(mediaList))
+                         .c_str());
+        return temp;
+    }
+
+    bool requestMediaChange(const QString& callID, const VectorMapStringString& mediaList)
+    {
+        return DRing::requestMediaChange(callID.toStdString(), convertVecMap(mediaList));
+    }
+
+    bool acceptWithMedia(const QString& callID, const VectorMapStringString& mediaList)
+    {
+        return DRing::acceptWithMedia(callID.toStdString(), convertVecMap(mediaList));
+    }
+
+    bool answerMediaChangeRequest(const QString& callID, const VectorMapStringString& mediaList)
+    {
+        return DRing::answerMediaChangeRequest(callID.toStdString(), convertVecMap(mediaList));
+    }
+    // END OF MULTISTREAM FUNCTIONS
+
     void playDTMF(const QString& key) { DRing::playDTMF(key.toStdString()); }
 
     void recordPlaybackSeek(double value) { DRing::recordPlaybackSeek(value); }
@@ -409,6 +450,10 @@ Q_SIGNALS: // SIGNALS
     void voiceMailNotify(const QString& accountId, int newCount, int oldCount, int urgentCount);
     void incomingMessage(const QString& callID, const QString& from, const MapStringString& message);
     void incomingCall(const QString& accountID, const QString& callID, const QString& from);
+    void incomingCallWithMedia(const QString& accountID,
+                               const QString& callID,
+                               const QString& from,
+                               const VectorMapStringString& mediaList);
     void recordPlaybackFilepath(const QString& callID, const QString& filepath);
     void conferenceCreated(const QString& confID);
     void conferenceChanged(const QString& confID, const QString& state);
@@ -421,7 +466,9 @@ Q_SIGNALS: // SIGNALS
     void videoMuted(const QString& callID, bool state);
     void peerHold(const QString& callID, bool state);
     void smartInfo(const MapStringString& info);
-    void remoteRecordingChanged(const QString &callID, const QString &peerNumber, bool remoteRecordingState);
+    void remoteRecordingChanged(const QString& callID,
+                                const QString& peerNumber,
+                                bool remoteRecordingState);
 };
 
 namespace org {
diff --git a/src/qtwrapper/conversions_wrap.hpp b/src/qtwrapper/conversions_wrap.hpp
index 965a8e115d1c1da739e9817819ea183e2016dc36..6d4dc42807f97fa5d3c679e6e273e7791e32f0d4 100644
--- a/src/qtwrapper/conversions_wrap.hpp
+++ b/src/qtwrapper/conversions_wrap.hpp
@@ -73,6 +73,16 @@ convertVecMap(const std::vector<std::map<std::string, std::string>>& m)
     return temp;
 }
 
+inline std::vector<std::map<std::string, std::string>>
+convertVecMap(const VectorMapStringString& m)
+{
+    std::vector<std::map<std::string, std::string>> temp;
+    for (const auto& x : m) {
+        temp.push_back(convertMap(x));
+    }
+    return temp;
+}
+
 inline QStringList
 convertStringList(const std::vector<std::string>& v)
 {