diff --git a/src/media/video/video_mixer.cpp b/src/media/video/video_mixer.cpp
index 6e00f0d263520b153818c5dcbcc026979827b122..7d121365a9dd64a0ed7257cf9afaf1083866eed3 100644
--- a/src/media/video/video_mixer.cpp
+++ b/src/media/video/video_mixer.cpp
@@ -49,12 +49,18 @@ struct VideoMixer::VideoMixerSource
     Observable<std::shared_ptr<MediaFrame>>* source {nullptr};
     int rotation {0};
     std::unique_ptr<MediaFilter> rotationFilter {nullptr};
-    std::unique_ptr<VideoFrame> update_frame;
-    std::unique_ptr<VideoFrame> render_frame;
-    void atomic_swap_render(std::unique_ptr<VideoFrame>& other)
+    std::shared_ptr<VideoFrame> render_frame;
+    void atomic_copy(const VideoFrame& other)
     {
         std::lock_guard<std::mutex> lock(mutex_);
-        render_frame.swap(other);
+        auto newFrame = std::make_shared<VideoFrame>();
+        newFrame->copyFrom(other);
+        render_frame = newFrame;
+    }
+
+    std::shared_ptr<VideoFrame> getRenderFrame() {
+        std::lock_guard<std::mutex> lock(mutex_);
+        return render_frame;
     }
 
     // Current render informations
@@ -188,6 +194,7 @@ VideoMixer::attached(Observable<std::shared_ptr<MediaFrame>>* ob)
     auto lock(rwMutex_.write());
 
     auto src = std::unique_ptr<VideoMixerSource>(new VideoMixerSource);
+    src->render_frame = std::make_shared<VideoFrame>();
     src->source = ob;
     sources_.emplace_back(std::move(src));
     layoutUpdated_ += 1;
@@ -220,13 +227,18 @@ VideoMixer::update(Observable<std::shared_ptr<MediaFrame>>* ob,
 
     for (const auto& x : sources_) {
         if (x->source == ob) {
-            if (!x->update_frame)
-                x->update_frame.reset(new VideoFrame);
-            else
-                x->update_frame->reset();
-            x->update_frame->copyFrom(*std::static_pointer_cast<VideoFrame>(
-                frame_p)); // copy frame content, it will be destroyed after return
-            x->atomic_swap_render(x->update_frame);
+#ifdef RING_ACCEL
+            std::shared_ptr<VideoFrame> frame;
+            try {
+                frame = HardwareAccel::transferToMainMemory(*std::static_pointer_cast<VideoFrame>(frame_p), AV_PIX_FMT_NV12);
+            } catch (const std::runtime_error& e) {
+                JAMI_ERR("Accel failure: %s", e.what());
+                return;
+            }
+            x->atomic_copy(*std::static_pointer_cast<VideoFrame>(frame));
+#else
+            x->atomic_copy(*std::static_pointer_cast<VideoFrame>(frame_p));
+#endif
             return;
         }
     }
@@ -265,8 +277,7 @@ VideoMixer::process()
             if (currentLayout_ != Layout::ONE_BIG or activeSource_ == x->source) {
                 // make rendered frame temporarily unavailable for update()
                 // to avoid concurrent access.
-                std::unique_ptr<VideoFrame> input;
-                x->atomic_swap_render(input);
+                std::shared_ptr<VideoFrame> input = x->getRenderFrame();
 
                 auto wantedIndex = i;
                 if (currentLayout_ == Layout::ONE_BIG) {
@@ -285,7 +296,9 @@ VideoMixer::process()
                     calc_position(x, wantedIndex);
 
                 if (input)
-                    successfullyRendered |= render_frame(output, *input, x);
+                    successfullyRendered |= render_frame(output, input, x);
+                else
+                    JAMI_WARN("Nothing to render for %p", x->source);
 
                 auto hasVideo = x->hasVideo;
                 x->hasVideo = input && successfullyRendered;
@@ -293,7 +306,6 @@ VideoMixer::process()
                     layoutUpdated_ += 1;
                     needsUpdate = true;
                 }
-                x->atomic_swap_render(input);
             } else if (needsUpdate) {
                 x->x = 0;
                 x->y = 0;
@@ -314,7 +326,7 @@ VideoMixer::process()
                         SourceInfo {x->source, x->x, x->y, x->w, x->h, x->hasVideo});
                 }
                 if (onSourcesUpdated_)
-                    (onSourcesUpdated_)(std::move(sourcesInfo));
+                    onSourcesUpdated_(std::move(sourcesInfo));
             }
         }
     }
@@ -330,44 +342,35 @@ VideoMixer::process()
 
 bool
 VideoMixer::render_frame(VideoFrame& output,
-                         const VideoFrame& input,
+                         const std::shared_ptr<VideoFrame>& input,
                          std::unique_ptr<VideoMixerSource>& source)
 {
-    if (!width_ or !height_ or !input.pointer() or input.pointer()->format == -1)
-        return false;
-
-#ifdef RING_ACCEL
-    std::shared_ptr<VideoFrame> frame;
-    try {
-        frame = HardwareAccel::transferToMainMemory(input, AV_PIX_FMT_NV12);
-    } catch (const std::runtime_error& e) {
-        JAMI_ERR("Accel failure: %s", e.what());
+    if (!width_ or !height_ or !input->pointer() or input->pointer()->format == -1)
         return false;
-    }
-#else
-    std::shared_ptr<VideoFrame> frame = input;
-#endif
 
     int cell_width = source->w;
     int cell_height = source->h;
     int xoff = source->x;
     int yoff = source->y;
 
-    int angle = frame->getOrientation();
+    int angle = input->getOrientation();
     const constexpr char filterIn[] = "mixin";
     if (angle != source->rotation) {
         source->rotationFilter = video::getTransposeFilter(angle,
                                                            filterIn,
-                                                           frame->width(),
-                                                           frame->height(),
-                                                           frame->format(),
+                                                           input->width(),
+                                                           input->height(),
+                                                           input->format(),
                                                            false);
         source->rotation = angle;
     }
+    std::shared_ptr<VideoFrame> frame;
     if (source->rotationFilter) {
-        source->rotationFilter->feedInput(frame->pointer(), filterIn);
+        source->rotationFilter->feedInput(input->pointer(), filterIn);
         frame = std::static_pointer_cast<VideoFrame>(
             std::shared_ptr<MediaFrame>(source->rotationFilter->readOutput()));
+    } else {
+        frame = input;
     }
 
     scaler_.scale_and_pad(*frame, output, xoff, yoff, cell_width, cell_height, true);
diff --git a/src/media/video/video_mixer.h b/src/media/video/video_mixer.h
index 70a38c0d3b89d17e0b5cf091ee993fd1df03beff..c55b9225bcee9dc386f790813522ed2c9663081d 100644
--- a/src/media/video/video_mixer.h
+++ b/src/media/video/video_mixer.h
@@ -92,7 +92,7 @@ private:
     struct VideoMixerSource;
 
     bool render_frame(VideoFrame& output,
-                      const VideoFrame& input,
+                      const std::shared_ptr<VideoFrame>& input,
                       std::unique_ptr<VideoMixerSource>& source);
 
     void calc_position(std::unique_ptr<VideoMixerSource>& source, int index);