diff --git a/src/conference.cpp b/src/conference.cpp
index c41f252243b8e314299cd83f65fb0485a1c33ce7..4c527b684d42d195ddf3c81fc1df04052a9d4196 100644
--- a/src/conference.cpp
+++ b/src/conference.cpp
@@ -1012,11 +1012,10 @@ Conference::resizeRemoteParticipants(ConfInfo& confInfo, std::string_view peerUR
         }
     }
 
+    const float zoomX = (float) remoteFrameWidth / localCell.w;
+    const float zoomY = (float) remoteFrameHeight / localCell.h;
     // Do the resize for each remote participant
     for (auto& remoteCell : confInfo) {
-        const float zoomX = (float) remoteFrameWidth / localCell.w;
-        const float zoomY = (float) remoteFrameHeight / localCell.h;
-
         remoteCell.x = remoteCell.x / zoomX + localCell.x;
         remoteCell.y = remoteCell.y / zoomY + localCell.y;
         remoteCell.w = remoteCell.w / zoomX;
@@ -1052,8 +1051,10 @@ Conference::mergeConfInfo(ConfInfo& newInfo, const std::string& peerURI)
     }
     // Send confInfo only if needed to avoid loops
     if (updateNeeded) {
-        std::lock_guard<std::mutex> lk(confInfoMutex_);
-        sendConferenceInfos();
+        // Trigger the layout update in the mixer because the frame resolution may
+        // change from participant to conference and cause a mismatch between
+        // confInfo layout and rendering layout.
+        getVideoMixer()->updateLayout();
     }
 }
 
diff --git a/src/media/video/video_mixer.cpp b/src/media/video/video_mixer.cpp
index 216142118ad69ef2ed63f94b991b2472b44cd94f..3bcf40ad8f1c1b9b0a9350a795168202fd1ef038 100644
--- a/src/media/video/video_mixer.cpp
+++ b/src/media/video/video_mixer.cpp
@@ -178,13 +178,19 @@ void
 VideoMixer::setActiveHost()
 {
     activeSource_ = videoLocalSecondary_ ? videoLocalSecondary_.get() : videoLocal_.get();
-    layoutUpdated_ += 1;
+    updateLayout();
 }
 
 void
 VideoMixer::setActiveParticipant(Observable<std::shared_ptr<MediaFrame>>* ob)
 {
     activeSource_ = ob;
+    updateLayout();
+}
+
+void
+VideoMixer::updateLayout()
+{
     layoutUpdated_ += 1;
 }
 
@@ -197,7 +203,7 @@ VideoMixer::attached(Observable<std::shared_ptr<MediaFrame>>* ob)
     src->render_frame = std::make_shared<VideoFrame>();
     src->source = ob;
     sources_.emplace_back(std::move(src));
-    layoutUpdated_ += 1;
+    updateLayout();
 }
 
 void
@@ -213,7 +219,7 @@ VideoMixer::detached(Observable<std::shared_ptr<MediaFrame>>* ob)
                 activeSource_ = videoLocalSecondary_ ? videoLocalSecondary_.get() : videoLocal_.get();
             }
             sources_.remove(x);
-            layoutUpdated_ += 1;
+            updateLayout();
             break;
         }
     }
@@ -285,7 +291,7 @@ VideoMixer::process()
                 // If orientation changed or if the first valid frame for source
                 // is received -> trigger layout calculation and confInfo update
                 if (x->rotation != input->getOrientation() or !x->w or !x->h) {
-                    layoutUpdated_ += 1;
+                    updateLayout();
                     needsUpdate = true;
                 }
 
@@ -313,7 +319,7 @@ VideoMixer::process()
                 auto hasVideo = x->hasVideo;
                 x->hasVideo = input && successfullyRendered;
                 if (hasVideo != x->hasVideo) {
-                    layoutUpdated_ += 1;
+                    updateLayout();
                     needsUpdate = true;
                 }
             } else if (needsUpdate) {
@@ -471,7 +477,7 @@ VideoMixer::setParameters(int width, int height, AVPixelFormat format)
         libav_utils::fillWithBlack(previous_p->pointer());
 
     start_sink();
-    layoutUpdated_ += 1;
+    updateLayout();
     startTime_ = av_gettime();
 }
 
diff --git a/src/media/video/video_mixer.h b/src/media/video/video_mixer.h
index 00f0d4ae404d741cc56fceab25aae0784674fd9a..872674670b6dfddee03585b0c62a0b5832ba7238 100644
--- a/src/media/video/video_mixer.h
+++ b/src/media/video/video_mixer.h
@@ -89,6 +89,8 @@ public:
 
     std::shared_ptr<VideoFrameActiveWriter>& getVideoLocal() { return videoLocal_; }
 
+    void updateLayout();
+
 private:
     NON_COPYABLE(VideoMixer);
     struct VideoMixerSource;