From b1904d27f09df80ee3ab8dc8c51bf0777dd9f6f0 Mon Sep 17 00:00:00 2001
From: Guillaume Roguez <guillaume.roguez@savoirfairelinux.com>
Date: Fri, 3 Jan 2014 15:49:28 -0500
Subject: [PATCH] * 37884: add scale_and_pad() to VideoScaler class

---
 daemon/src/video/video_mixer.cpp  | 15 +++----------
 daemon/src/video/video_scaler.cpp | 35 +++++++++++++++++++++++++++++++
 daemon/src/video/video_scaler.h   |  3 +++
 3 files changed, 41 insertions(+), 12 deletions(-)

diff --git a/daemon/src/video/video_mixer.cpp b/daemon/src/video/video_mixer.cpp
index bbceb20bf4..16879b3290 100644
--- a/daemon/src/video/video_mixer.cpp
+++ b/daemon/src/video/video_mixer.cpp
@@ -97,7 +97,6 @@ void VideoMixer::update(Observable<std::shared_ptr<VideoFrame> >* ob,
 void VideoMixer::render_frame(VideoFrame& input, const int index)
 {
     VideoScaler scaler;
-    VideoFrame scaled_input;
 
     if (!width_ or !height_)
         return;
@@ -118,18 +117,10 @@ void VideoMixer::render_frame(VideoFrame& input, const int index)
     const int zoom = ceil(sqrt(n));
     const int cell_width = width_ / zoom;
     const int cell_height = height_ / zoom;
+    const int xoff = (index % zoom) * cell_width;
+    const int yoff = (index / zoom) * cell_height;
 
-    if (!scaled_input.allocBuffer(cell_width, cell_height,
-                                  VIDEO_PIXFMT_YUV420P)) {
-        ERROR("VideoFrame::allocBuffer() failed");
-        return;
-    }
-
-    int xoff = (index % zoom) * cell_width;
-    int yoff = (index / zoom) * cell_height;
-
-    scaler.scale(input, scaled_input);
-    output.blit(scaled_input, xoff, yoff);
+    scaler.scale_and_pad(input, output, xoff, yoff, cell_width, cell_height);
 
     publishFrame();
 }
diff --git a/daemon/src/video/video_scaler.cpp b/daemon/src/video/video_scaler.cpp
index 30ff53b620..bcbe18f5dc 100644
--- a/daemon/src/video/video_scaler.cpp
+++ b/daemon/src/video/video_scaler.cpp
@@ -62,6 +62,41 @@ void VideoScaler::scale(VideoFrame &input, VideoFrame &output)
               input_frame->height, output_frame->data, output_frame->linesize);
 }
 
+void VideoScaler::scale_and_pad(VideoFrame &input, VideoFrame &output,
+                                unsigned xoff, unsigned yoff,
+                                unsigned dest_width, unsigned dest_height)
+{
+    AVFrame *input_frame = input.get();
+    AVFrame *output_frame = output.get();
+    uint8_t *data[AV_NUM_DATA_POINTERS];
+
+    for (int i = 0; i < AV_NUM_DATA_POINTERS; i++) {
+        if (output_frame->data[i]) {
+            const unsigned divisor = i == 0 ? 1 : 2;
+            unsigned offset = (yoff * output_frame->linesize[i] + xoff) / divisor;
+            data[i] = output_frame->data[i] + offset;
+        } else
+            data[i] = 0;
+    }
+
+    ctx_ = sws_getCachedContext(ctx_,
+                                input_frame->width,
+                                input_frame->height,
+                                (AVPixelFormat) input_frame->format,
+                                dest_width,
+                                dest_height,
+                                (AVPixelFormat) output_frame->format,
+                                mode_,
+                                NULL, NULL, NULL);
+    if (!ctx_) {
+        ERROR("Unable to create a scaler context");
+        return;
+    }
+
+    sws_scale(ctx_, input_frame->data, input_frame->linesize, 0,
+              input_frame->height, data, output_frame->linesize);
+}
+
 void VideoScaler::reset()
 {
     if (ctx_) {
diff --git a/daemon/src/video/video_scaler.h b/daemon/src/video/video_scaler.h
index ad7bb70c1a..96e09290e7 100644
--- a/daemon/src/video/video_scaler.h
+++ b/daemon/src/video/video_scaler.h
@@ -46,6 +46,9 @@ public:
     ~VideoScaler();
     void scale(VideoFrame &input, VideoFrame &output);
     void reset();
+    void scale_and_pad(VideoFrame &input, VideoFrame &output,
+                       unsigned xoff, unsigned yoff,
+                       unsigned dest_width, unsigned dest_height);
 
 private:
     NON_COPYABLE(VideoScaler);
-- 
GitLab