diff --git a/src/call.h b/src/call.h
index 605aba22ba6de74129f1c5c9447d369964621cb9..c74ac8ceb9190e807071492a9c9cf000c315be2c 100644
--- a/src/call.h
+++ b/src/call.h
@@ -299,7 +299,7 @@ public:
      */
     virtual bool offhold(OnReadyCb&& cb) = 0;
 
-    virtual void sendKeyframe() = 0;
+    virtual void sendKeyframe(int streamIdx = -1) = 0;
 
     /**
      * Check wether ICE is enabled for media
diff --git a/src/sip/sipcall.cpp b/src/sip/sipcall.cpp
index fc037ae4ba6379301ba138e85e593336b8dae9cf..0654edd3e8fc87a0171e6d1f4168e80032867c3d 100644
--- a/src/sip/sipcall.cpp
+++ b/src/sip/sipcall.cpp
@@ -250,17 +250,18 @@ SIPCall::configureRtpSession(const std::shared_ptr<RtpSession>& rtpSession,
 #ifdef ENABLE_VIDEO
     if (localMedia.type == MediaType::MEDIA_VIDEO) {
         auto videoRtp = std::dynamic_pointer_cast<video::VideoRtpSession>(rtpSession);
-        assert(videoRtp);
-        videoRtp->setRequestKeyFrameCallback([w = weak()] {
-            runOnMainThread([w] {
+        assert(videoRtp && mediaAttr);
+        auto streamIdx = findRtpStreamIndex(mediaAttr->label_);
+        videoRtp->setRequestKeyFrameCallback([w = weak(), streamIdx] {
+            runOnMainThread([w = std::move(w), streamIdx] {
                 if (auto thisPtr = w.lock())
-                    thisPtr->requestKeyframe();
+                    thisPtr->requestKeyframe(streamIdx);
             });
         });
-        videoRtp->setChangeOrientationCallback([w = weak()](int angle) {
-            runOnMainThread([w, angle] {
+        videoRtp->setChangeOrientationCallback([w = weak(), streamIdx](int angle) {
+            runOnMainThread([w, angle, streamIdx] {
                 if (auto thisPtr = w.lock())
-                    thisPtr->setVideoOrientation(angle);
+                    thisPtr->setVideoOrientation(streamIdx, angle);
             });
         });
     }
@@ -602,17 +603,21 @@ SIPCall::updateRecState(bool state)
 }
 
 void
-SIPCall::requestKeyframe()
+SIPCall::requestKeyframe(int streamIdx)
 {
     auto now = clock::now();
     if ((now - lastKeyFrameReq_) < MS_BETWEEN_2_KEYFRAME_REQUEST
         and lastKeyFrameReq_ != time_point::min())
         return;
 
-    constexpr auto BODY = "<?xml version=\"1.0\" encoding=\"utf-8\" ?>"
-                          "<media_control><vc_primitive><to_encoder>"
-                          "<picture_fast_update/>"
-                          "</to_encoder></vc_primitive></media_control>"sv;
+    std::string streamIdPart;
+    if (streamIdx != -1)
+        streamIdPart = fmt::format("<stream_id>{}</stream_id>", streamIdx);
+    std::string BODY = "<?xml version=\"1.0\" encoding=\"utf-8\" ?>"
+                       "<media_control><vc_primitive> "
+                       + streamIdPart + "<to_encoder>"
+                       + "<picture_fast_update/>"
+                         "</to_encoder></vc_primitive></media_control>";
     JAMI_DBG("Sending video keyframe request via SIP INFO");
     try {
         sendSIPInfo(BODY, "media_control+xml");
@@ -1441,16 +1446,18 @@ SIPCall::carryingDTMFdigits(char code)
 }
 
 void
-SIPCall::setVideoOrientation(int rotation)
+SIPCall::setVideoOrientation(int streamIdx, int rotation)
 {
+    std::string streamIdPart;
+    if (streamIdx != -1)
+        streamIdPart = fmt::format("<stream_id>{}</stream_id>", streamIdx);
     std::string sip_body = "<?xml version=\"1.0\" encoding=\"utf-8\" ?>"
                            "<media_control><vc_primitive><to_encoder>"
                            "<device_orientation="
-                           + std::to_string(-rotation)
-                           + "/>"
-                             "</to_encoder></vc_primitive></media_control>";
+                           + std::to_string(-rotation) + "/>" + "</to_encoder>" + streamIdPart
+                           + "</vc_primitive></media_control>";
 
-    JAMI_DBG("Sending device orientation via SIP INFO %d", rotation);
+    JAMI_DBG("Sending device orientation via SIP INFO %d for stream %u", rotation, streamIdx);
 
     sendSIPInfo(sip_body, "media_control+xml");
 }
@@ -1586,14 +1593,23 @@ SIPCall::onAnswered()
 }
 
 void
-SIPCall::sendKeyframe()
+SIPCall::sendKeyframe(int streamIdx)
 {
 #ifdef ENABLE_VIDEO
-    dht::ThreadPool::computation().run([w = weak()] {
+    dht::ThreadPool::computation().run([w = weak(), streamIdx] {
         if (auto sthis = w.lock()) {
             JAMI_DBG("handling picture fast update request");
-            for (const auto& videoRtp : sthis->getRtpSessionList(MediaType::MEDIA_VIDEO))
-                std::static_pointer_cast<video::VideoRtpSession>(videoRtp)->forceKeyFrame();
+            if (streamIdx == -1) {
+                for (const auto& videoRtp : sthis->getRtpSessionList(MediaType::MEDIA_VIDEO))
+                    std::static_pointer_cast<video::VideoRtpSession>(videoRtp)->forceKeyFrame();
+            } else if (streamIdx > -1 && streamIdx < sthis->rtpStreams_.size()) {
+                // Apply request for wanted stream
+                auto& stream = sthis->rtpStreams_[streamIdx];
+                if (stream.rtpSession_
+                    && stream.rtpSession_->getMediaType() == MediaType::MEDIA_VIDEO)
+                    std::static_pointer_cast<video::VideoRtpSession>(stream.rtpSession_)
+                        ->forceKeyFrame();
+            }
         }
     });
 #endif
@@ -2196,9 +2212,8 @@ SIPCall::updateRemoteMedia()
                      remoteMedia->toString().c_str());
             rtpStream.rtpSession_->setMuted(remoteMedia->muted_, RtpSession::Direction::RECV);
             // Request a key-frame if we are un-muting the video
-            if (not remoteMedia->muted_) {
-                requestKeyframe();
-            }
+            if (not remoteMedia->muted_)
+                requestKeyframe(findRtpStreamIndex(remoteMedia->label_));
         }
     }
 }
@@ -2993,12 +3008,19 @@ SIPCall::exitConference()
 
 #ifdef ENABLE_VIDEO
 void
-SIPCall::setRotation(int rotation)
+SIPCall::setRotation(int streamIdx, int rotation)
 {
     rotation_ = rotation;
-    // For now, only apply rotation on all videos
-    for (auto const& videoRtp : getRtpSessionList(MediaType::MEDIA_VIDEO))
-        std::static_pointer_cast<video::VideoRtpSession>(videoRtp)->setRotation(rotation);
+    if (streamIdx == -1) {
+        for (const auto& videoRtp : getRtpSessionList(MediaType::MEDIA_VIDEO))
+            std::static_pointer_cast<video::VideoRtpSession>(videoRtp)->setRotation(rotation);
+    } else if (streamIdx > -1 && streamIdx < rtpStreams_.size()) {
+        // Apply request for wanted stream
+        auto& stream = rtpStreams_[streamIdx];
+        if (stream.rtpSession_ && stream.rtpSession_->getMediaType() == MediaType::MEDIA_VIDEO)
+            std::static_pointer_cast<video::VideoRtpSession>(stream.rtpSession_)
+                ->setRotation(rotation);
+    }
 }
 
 void
diff --git a/src/sip/sipcall.h b/src/sip/sipcall.h
index 5568a1726d2989b13be53eb0647cd384a94a89cd..5a642fdfeb6e9f94e16453946b03ade7d2d134b2 100644
--- a/src/sip/sipcall.h
+++ b/src/sip/sipcall.h
@@ -142,7 +142,7 @@ public:
     void restartMediaSender() override;
     std::shared_ptr<AccountCodecInfo> getAudioCodec() const override;
     std::shared_ptr<AccountCodecInfo> getVideoCodec() const override;
-    void sendKeyframe() override;
+    void sendKeyframe(int streamIdx = -1) override;
     bool isIceEnabled() const override;
     std::map<std::string, std::string> getDetails() const override;
     void enterConference(std::shared_ptr<Conference> conference) override;
@@ -236,7 +236,7 @@ public:
 
     void sendSIPInfo(std::string_view body, std::string_view subtype);
 
-    void requestKeyframe();
+    void requestKeyframe(int streamIdx = -1);
 
     void updateRecState(bool state) override;
 
@@ -275,7 +275,7 @@ public:
 
     std::shared_ptr<AudioRtpSession> getAudioRtp() const;
 #ifdef ENABLE_VIDEO
-    void setRotation(int rotation);
+    void setRotation(int streamIdx, int rotation);
 #endif
     // Get the list of current RTP sessions
     std::vector<std::shared_ptr<RtpSession>> getRtpSessionList(
@@ -327,9 +327,10 @@ private:
 
     /**
      * Send device orientation through SIP INFO
-     * @param rotation Device orientation (0/90/180/270) (counterclockwise)
+     * @param streamIdx  The stream to rotate
+     * @param rotation   Device orientation (0/90/180/270) (counterclockwise)
      */
-    void setVideoOrientation(int rotation);
+    void setVideoOrientation(int streamIdx, int rotation);
 
     mutable std::mutex transportMtx_ {};
 
diff --git a/src/sip/sipvoiplink.cpp b/src/sip/sipvoiplink.cpp
index 43534721b21c3d97728677ee61f9e113d21a0115..95cf5ccb3455bc291b77682a0d0e49e489824761 100644
--- a/src/sip/sipvoiplink.cpp
+++ b/src/sip/sipvoiplink.cpp
@@ -1169,12 +1169,29 @@ handleMediaControl(SIPCall& call, pjsip_msg_body* body)
 
         /* Apply and answer the INFO request */
         static constexpr auto PICT_FAST_UPDATE = "picture_fast_update"sv;
+        static constexpr auto STREAM_ID = "stream_id"sv;
         static constexpr auto DEVICE_ORIENTATION = "device_orientation"sv;
         static constexpr auto RECORDING_STATE = "recording_state"sv;
         static constexpr auto MUTE_STATE = "mute_state"sv;
 
+        int streamIdx = -1;
+        if (body_msg.find(STREAM_ID) != std::string_view::npos) {
+            // Note: here we use the index of the RTP stream, not it's label!
+            // Indeed, both side will have different labels as they have different call ids
+            static const std::regex STREAMID_REGEX("<stream_id>([0-9]+)</stream_id>");
+            std::svmatch matched_pattern;
+            std::regex_search(body_msg, matched_pattern, STREAMID_REGEX);
+            if (matched_pattern.ready() && !matched_pattern.empty() && matched_pattern[1].matched) {
+                try {
+                    streamIdx = std::stoi(matched_pattern[1]);
+                } catch (const std::exception& e) {
+                    JAMI_WARN("Error parsing stream index: %s", e.what());
+                }
+            }
+        }
+
         if (body_msg.find(PICT_FAST_UPDATE) != std::string_view::npos) {
-            call.sendKeyframe();
+            call.sendKeyframe(streamIdx);
             return true;
         } else if (body_msg.find(DEVICE_ORIENTATION) != std::string_view::npos) {
             static const std::regex ORIENTATION_REGEX("device_orientation=([-+]?[0-9]+)");
@@ -1191,7 +1208,7 @@ handleMediaControl(SIPCall& call, pjsip_msg_body* body)
                         rotation -= 360;
                     JAMI_WARN("Rotate video %d deg.", rotation);
 #ifdef ENABLE_VIDEO
-                    call.setRotation(rotation);
+                    call.setRotation(streamIdx, rotation);
 #endif
                 } catch (const std::exception& e) {
                     JAMI_WARN("Error parsing angle: %s", e.what());
diff --git a/src/sip/sipvoiplink.h b/src/sip/sipvoiplink.h
index b6e1beaaa7bfe4e11af921165f0afebde2f6ebae..f44bcc3533544e9da0862fad696f859a5c26e88a 100644
--- a/src/sip/sipvoiplink.h
+++ b/src/sip/sipvoiplink.h
@@ -165,10 +165,6 @@ private:
     std::atomic_bool running_ {true};
     std::thread sipThread_;
 
-#ifdef ENABLE_VIDEO
-    void requestKeyframe(const std::string& callID);
-#endif
-
     friend class SIPTest;
 };