From 0668168a110e37555ee69d3a79b157862529ba7f Mon Sep 17 00:00:00 2001
From: Kateryna Kostiuk <kateryna.kostiuk@savoirfairelinux.com>
Date: Thu, 7 May 2020 20:50:56 -0400
Subject: [PATCH] video: use openGL when metal is not available

Change-Id: Ic2d19d19da72b71f73f12d3efab75c9bb384d2fb
---
 CMakeLists.txt                 |   3 +
 src/CurrentCallVC.mm           |  84 ++++++++++----------
 src/RecordFileVC.mm            |   8 +-
 src/VideoCommon.mm             |  25 +++++-
 src/VideoPrefsVC.mm            |  16 ++--
 src/views/CallLayer.h          |   6 +-
 src/views/CallLayer.mm         | 140 ++++++++++++++++++++++++++-------
 src/views/CallMTKView.h        |   7 +-
 src/views/CallMTKView.mm       |   3 +-
 src/views/RenderingView.h      |  26 ++++++
 src/views/RenderingView.mm     |  89 +++++++++++++++++++++
 src/views/VideoRendering.h     |  29 +++++++
 ui/Base.lproj/CurrentCall.xib  |  38 ++++-----
 ui/Base.lproj/RecordFileVC.xib |  13 +--
 ui/Base.lproj/VideoPrefs.xib   |  12 +--
 15 files changed, 374 insertions(+), 125 deletions(-)
 create mode 100644 src/views/RenderingView.h
 create mode 100644 src/views/RenderingView.mm
 create mode 100644 src/views/VideoRendering.h

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 4033aa0b..1e4ae52f 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -234,6 +234,9 @@ SET(ringclient_VIEWS
    src/views/GradientView.mm
    src/views/MovableView.h
    src/views/MovableView.mm
+   src/views/RenderingView.h
+   src/views/RenderingView.mm
+   src/views/VideoRendering.h
 )
 
 SET(ringclient_OTHERS
diff --git a/src/CurrentCallVC.mm b/src/CurrentCallVC.mm
index c51af7ac..1316ea86 100644
--- a/src/CurrentCallVC.mm
+++ b/src/CurrentCallVC.mm
@@ -51,6 +51,7 @@ extern "C" {
 #import "VideoCommon.h"
 #import "views/GradientView.h"
 #import "views/MovableView.h"
+#import "views/RenderingView.h"
 
 @interface CurrentCallVC () <NSPopoverDelegate> {
     QString convUid_;
@@ -96,12 +97,12 @@ extern "C" {
 
 // Video
 @property (unsafe_unretained) IBOutlet CallView *videoView;
-@property (unsafe_unretained) IBOutlet CallMTKView *previewView;
+@property (unsafe_unretained) IBOutlet RenderingView *previewView;
 @property (unsafe_unretained) IBOutlet MovableView *movableBaseForView;
 @property (unsafe_unretained) IBOutlet NSView* hidePreviewBackground;
 @property (unsafe_unretained) IBOutlet NSButton* hidePreviewButton;
 
-@property (unsafe_unretained) IBOutlet CallMTKView *videoMTKView;
+@property (unsafe_unretained) IBOutlet RenderingView *distantView;
 
 @property RendererConnectionsHolder* renderConnections;
 @property QMetaObject::Connection videoStarted;
@@ -373,13 +374,13 @@ CVPixelBufferRef pixelBufferPreview;
             [headerGradientView setHidden:YES];
             [controlsPanel setHidden:YES];
             [controlsStackView setHidden:YES];
-            [self.videoMTKView fillWithBlack];
+            [self.distantView fillWithBlack];
             [self.previewView fillWithBlack];
             [hidePreviewBackground setHidden:YES];
             [self.previewView setHidden: YES];
-            [self.videoMTKView setHidden: YES];
-            self.previewView.stopRendering = true;
-            self.videoMTKView.stopRendering = true;
+            [self.distantView setHidden: YES];
+            self.previewView.videoRunning = NO;
+            self.distantView.videoRunning = NO;
             [backgroundImage setHidden:NO];
             [bluerBackgroundEffect setHidden:NO];
             break;
@@ -392,13 +393,13 @@ CVPixelBufferRef pixelBufferPreview;
             [backgroundImage setHidden:NO];
             [bluerBackgroundEffect setHidden:NO];
             if(!currentCall.isAudioOnly) {
-                [self.videoMTKView fillWithBlack];
+                [self.distantView fillWithBlack];
                 [self.previewView fillWithBlack];
                 [hidePreviewBackground setHidden:YES];
                 [self.previewView setHidden: YES];
-                [self.videoMTKView setHidden: YES];
-                self.previewView.stopRendering = true;
-                self.videoMTKView.stopRendering = true;
+                [self.distantView setHidden: YES];
+                self.previewView.videoRunning = NO;
+                self.distantView.videoRunning = NO;
             }
             break;
         case Status::INACTIVE:
@@ -436,19 +437,19 @@ CVPixelBufferRef pixelBufferPreview;
 
 -(void) setUpVideoCallView {
     [previewView fillWithBlack];
-    [self.videoMTKView fillWithBlack];
+    [self.distantView fillWithBlack];
     [previewView setHidden: NO];
-    [self.videoMTKView setHidden:NO];
-    [hidePreviewBackground setHidden: self.previewView.stopRendering];
+    [self.distantView setHidden:NO];
+    [hidePreviewBackground setHidden: !self.previewView.videoRunning];
     [bluerBackgroundEffect setHidden:YES];
     [backgroundImage setHidden:YES];
-    self.previewView.stopRendering = false;
-    self.videoMTKView.stopRendering = false;
+    self.previewView.videoRunning = true;
+    self.distantView.videoRunning = true;
 }
 
 -(void) setUpAudioOnlyView {
     [self.previewView setHidden: YES];
-    [self.videoMTKView setHidden: YES];
+    [self.distantView setHidden: YES];
     [hidePreviewBackground setHidden: YES];
     [bluerBackgroundEffect setHidden:NO];
     [backgroundImage setHidden:NO];
@@ -536,11 +537,11 @@ CVPixelBufferRef pixelBufferPreview;
                          if (id == lrc::api::video::PREVIEW_RENDERER_ID) {
                              [self.previewView setHidden:NO];
                              [hidePreviewBackground setHidden: NO];
-                             self.previewView.stopRendering = false;
+                             self.previewView.videoRunning = true;
                          } else if ([self isCurrentCall: id]) {
                              [self mouseIsMoving: NO];
-                             self.videoMTKView.stopRendering = false;
-                             [self.videoMTKView setHidden:NO];
+                             self.distantView.videoRunning = true;
+                             [self.distantView setHidden:NO];
                              [bluerBackgroundEffect setHidden:YES];
                              [backgroundImage setHidden:YES];
                          }
@@ -551,11 +552,11 @@ CVPixelBufferRef pixelBufferPreview;
                      [=](const QString& id) {
                          if (id == lrc::api::video::PREVIEW_RENDERER_ID) {
                              [self.previewView setHidden:YES];
-                             self.previewView.stopRendering = true;
+                             self.previewView.videoRunning = false;
                          } else if ([self isCurrentCall: id]) {
                              [self mouseIsMoving: YES];
-                             self.videoMTKView.stopRendering = true;
-                             [self.videoMTKView setHidden:YES];
+                             self.distantView.videoRunning = false;
+                             [self.distantView setHidden:YES];
                              [bluerBackgroundEffect setHidden:NO];
                              [backgroundImage setHidden:NO];
                          }
@@ -569,46 +570,47 @@ CVPixelBufferRef pixelBufferPreview;
                              if(!renderer->isRendering()) {
                                  return;
                              }
-                             [hidePreviewBackground setHidden: self.previewView.stopRendering];
-                             [self renderer: renderer renderFrameForPreviewView:previewView];
+                             [hidePreviewBackground setHidden: !self.previewView.videoRunning];
+                             [self rendererPreview: renderer];
                          } else if ([self isCurrentCall: id]) {
                              auto renderer = &mediaModel->getRenderer(id);
                              if(!renderer->isRendering()) {
                                  return;
                              }
-                             [self renderer:renderer renderFrameForDistantView: self.videoMTKView];
+                             [self rendererDistantView: renderer];
                          }
                      });
 }
 
--(void) renderer: (const lrc::api::video::Renderer*)renderer renderFrameForPreviewView:(CallMTKView*) view
-{
+-(void) rendererDistantView: (const lrc::api::video::Renderer*)renderer {
     @autoreleasepool {
         auto framePtr = renderer->currentAVFrame();
         auto frame = framePtr.get();
-        if(!frame || !frame->width || !frame->height) {
+        if(!frame || !frame->width || !frame->height)  {
             return;
         }
         auto frameSize = CGSizeMake(frame->width, frame->height);
         auto rotation = 0;
+        if (auto matrix = av_frame_get_side_data(frame, AV_FRAME_DATA_DISPLAYMATRIX)) {
+            const int32_t* data = reinterpret_cast<int32_t*>(matrix->data);
+            rotation = av_display_rotation_get(data);
+        }
         if (frame->data[3] != NULL && (CVPixelBufferRef)frame->data[3]) {
-            [view renderWithPixelBuffer:(CVPixelBufferRef)frame->data[3]
+            [self.distantView renderWithPixelBuffer: (CVPixelBufferRef)frame->data[3]
                                    size: frameSize
                                rotation: rotation
-                              fillFrame: true];
-            return;
+                              fillFrame: false];
         }
-        else if (CVPixelBufferRef pixelBuffer = [self getBufferForPreviewFromFrame:frame]) {
-            [view renderWithPixelBuffer: pixelBuffer
+        if (CVPixelBufferRef pixelBuffer = [self getBufferForDistantViewFromFrame:frame]) {
+            [self.distantView renderWithPixelBuffer: pixelBuffer
                                    size: frameSize
                                rotation: rotation
-                              fillFrame: true];
+                              fillFrame: false];
         }
     }
 }
 
--(void) renderer: (const lrc::api::video::Renderer*)renderer renderFrameForDistantView:(CallMTKView*) view
-{
+-(void) rendererPreview: (const lrc::api::video::Renderer*)renderer {
     @autoreleasepool {
         auto framePtr = renderer->currentAVFrame();
         auto frame = framePtr.get();
@@ -622,16 +624,16 @@ CVPixelBufferRef pixelBufferPreview;
             rotation = av_display_rotation_get(data);
         }
         if (frame->data[3] != NULL && (CVPixelBufferRef)frame->data[3]) {
-            [view renderWithPixelBuffer: (CVPixelBufferRef)frame->data[3]
+            [self.previewView renderWithPixelBuffer: (CVPixelBufferRef)frame->data[3]
                                    size: frameSize
                                rotation: rotation
                               fillFrame: false];
         }
-        if (CVPixelBufferRef pixelBuffer = [self getBufferForDistantViewFromFrame:frame]) {
-            [view renderWithPixelBuffer: pixelBuffer
+        if (CVPixelBufferRef pixelBuffer = [self getBufferForPreviewFromFrame:frame]) {
+            [self.previewView renderWithPixelBuffer: pixelBuffer
                                    size: frameSize
                                rotation: rotation
-                              fillFrame: false];
+                              fillFrame: true];
         }
     }
 }
@@ -700,7 +702,7 @@ CVPixelBufferRef pixelBufferPreview;
     [backgroundImage setHidden:NO];
     backgroundImage.layer.contents = nil;
     [self.previewView setHidden:YES];
-    [self.videoMTKView setHidden:YES];
+    [self.distantView setHidden:YES];
 
     contactNameLabel.textColor = [NSColor highlightColor];
     contactNameLabel.textColor = [NSColor highlightColor];
diff --git a/src/RecordFileVC.mm b/src/RecordFileVC.mm
index 9a09b6d1..edd1ce6c 100644
--- a/src/RecordFileVC.mm
+++ b/src/RecordFileVC.mm
@@ -21,8 +21,8 @@
 #import "AppDelegate.h"
 #import "VideoCommon.h"
 #import "views/HoverButton.h"
-#import "views/CallMTKView.h"
 #import "views/NSColor+RingTheme.h"
+#import "views/RenderingView.h"
 #import "NSString+Extensions.h"
 
 //lrc
@@ -32,7 +32,7 @@
 #import <AVFoundation/AVFoundation.h>
 
 @interface RecordFileVC ()
-@property (unsafe_unretained) IBOutlet CallMTKView* previewView;
+@property (unsafe_unretained) IBOutlet RenderingView* previewView;
 
 @property (unsafe_unretained) IBOutlet NSTextField* timeLabel;
 @property (unsafe_unretained) IBOutlet NSTextField* infoLabel;
@@ -106,7 +106,7 @@ previewView, timeLabel, recordOnOffButton, sendButton, fileImage, infoLabel, tim
 
 #pragma mark - dispaly
 
--(void) renderer: (const lrc::api::video::Renderer*)renderer renderFrameForView:(CallMTKView*) view
+-(void) renderer: (const lrc::api::video::Renderer*)renderer renderFrameForView:(RenderingView*) view
 {
     @autoreleasepool {
         const CGSize frameSize = [VideoCommon fillPixelBuffr:&pixBuf
@@ -270,7 +270,7 @@ previewView, timeLabel, recordOnOffButton, sendButton, fileImage, infoLabel, tim
     }
     [previewView fillWithBlack];
 
-    self.previewView.stopRendering = false;
+    self.previewView.videoRunning = true;
     [self connectPreviewSignals];
     avModel->stopPreview();
     avModel->startPreview();
diff --git a/src/VideoCommon.mm b/src/VideoCommon.mm
index 5e3be633..70ff004a 100644
--- a/src/VideoCommon.mm
+++ b/src/VideoCommon.mm
@@ -122,10 +122,27 @@ extern "C" {
         return;
     }
     base = static_cast<uint8_t*>(CVPixelBufferGetBaseAddressOfPlane(pixelBuffer, 1));
-    for(size_t i = 0; i < frame->height / 2 * bytesPerRowUV / 2; i++ ){
-        *base++ = frame->data[1][i];
-        *base++ = frame->data[2][i];
-   }
+    if (bytesPerRowUV == frame->linesize[1] * 2) {
+        for(size_t i = 0; i < frame->height / 2 * bytesPerRowUV / 2; i++ ) {
+            *base++ = frame->data[1][i];
+            *base++ = frame->data[2][i];
+        }
+    } else {
+        uint32_t size = frame->linesize[1] * frame->height / 2;
+        uint8_t* dstData = new uint8_t[2 * size];
+        for (int i = 0; i < 2 * size; i++){
+            if (i % 2 == 0){
+                dstData[i] = frame->data[1][i/2];
+            }else {
+                dstData[i] = frame->data[2][i/2];
+            }
+        }
+        [VideoCommon copyLineByLineSrc: dstData
+                                toDest: base
+                           srcLinesize: frame->linesize[1] * 2
+                          destLinesize: bytesPerRowUV
+                                height: frame->height/2];
+    }
     CVPixelBufferUnlockBaseAddress(pixelBuffer, 0);
 }
 
diff --git a/src/VideoPrefsVC.mm b/src/VideoPrefsVC.mm
index ff0680de..ed9739a0 100644
--- a/src/VideoPrefsVC.mm
+++ b/src/VideoPrefsVC.mm
@@ -18,7 +18,7 @@
  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.
  */
 #import "VideoPrefsVC.h"
-#import "views/CallMTKView.h"
+#import "views/RenderingView.h"
 #import "AppDelegate.h"
 #import "VideoCommon.h"
 
@@ -36,7 +36,7 @@ extern "C" {
 
 @interface VideoPrefsVC ()
 
-@property  IBOutlet CallMTKView* previewView;
+@property  IBOutlet RenderingView* previewView;
 @property (assign) IBOutlet NSPopUpButton* videoDevicesList;
 @property (assign) IBOutlet NSPopUpButton* sizesList;
 @property (assign) IBOutlet NSPopUpButton* ratesList;
@@ -85,7 +85,7 @@ QString currentVideoDevice;
     QObject::disconnect(deviceEvent);
     AppDelegate* appDelegate = (AppDelegate *)[[NSApplication sharedApplication] delegate];
     if (![appDelegate getActiveCalls].size()) {
-        self.previewView.stopRendering = true;
+        self.previewView.videoRunning = false;
         avModel->stopPreview();
         [previewView fillWithBlack];
     }
@@ -162,7 +162,7 @@ QString currentVideoDevice;
                          if (id != lrc::api::video::PREVIEW_RENDERER_ID) {
                              return;
                          }
-                        self.previewView.stopRendering = false;
+                        self.previewView.videoRunning = true;
                         QObject::disconnect(frameUpdated);
                         QObject::disconnect(previewStarted);
                         QObject::disconnect(previewStopped);
@@ -187,7 +187,7 @@ QString currentVideoDevice;
                                                                    ::PREVIEW_RENDERER_ID) {
                                                                    return;
                                                                }
-                                                               self.previewView.stopRendering = true;
+                                                               self.previewView.videoRunning = false;
                                                                QObject::disconnect(previewStopped);
                                                                QObject::disconnect(frameUpdated);
                          });
@@ -203,7 +203,7 @@ QString currentVideoDevice;
                                        bool updatePreview = avModel->getRenderer(lrc::api ::video::PREVIEW_RENDERER_ID).isRendering() && (defaultDevice != currentVideoDevice);
                                        if (updatePreview) {
                                            [previewView fillWithBlack];
-                                           self.previewView.stopRendering = true;
+                                           self.previewView.videoRunning = false;
                                            [self startPreview];
                                        }
                                        [self addDevices];
@@ -212,7 +212,7 @@ QString currentVideoDevice;
 
 #pragma mark - dispaly
 
--(void) renderer: (const lrc::api::video::Renderer*)renderer renderFrameForView:(CallMTKView*) view
+-(void) renderer: (const lrc::api::video::Renderer*)renderer renderFrameForView:(RenderingView*) view
 {
     @autoreleasepool {
         auto framePtr = renderer->currentAVFrame();
@@ -272,7 +272,7 @@ QString currentVideoDevice;
     AppDelegate* appDelegate = (AppDelegate *)[[NSApplication sharedApplication] delegate];
     auto calls = [appDelegate getActiveCalls];
     if (calls.empty()) {
-        self.previewView.stopRendering = false;
+        self.previewView.videoRunning = true;
         [self connectPreviewSignals];
         avModel->stopPreview();
         avModel->startPreview();
diff --git a/src/views/CallLayer.h b/src/views/CallLayer.h
index 86d21c79..f604e29e 100644
--- a/src/views/CallLayer.h
+++ b/src/views/CallLayer.h
@@ -20,11 +20,9 @@
 #import <Cocoa/Cocoa.h>
 #import <QSize>
 #import <video/renderer.h>
+#import "VideoRendering.h"
 
-@interface CallLayer : NSOpenGLLayer
+@interface CallLayer : NSOpenGLLayer <VideoRendering>
 
-@property BOOL videoRunning;
-
-- (void) setCurrentFrame:(Video::Frame)framePtr;
 
 @end
diff --git a/src/views/CallLayer.mm b/src/views/CallLayer.mm
index 3dd5fd32..4e03fa9d 100644
--- a/src/views/CallLayer.mm
+++ b/src/views/CallLayer.mm
@@ -26,13 +26,14 @@ static const GLchar* vShaderSrc = R"glsl(
 in vec2 in_Pos;
 in vec2 in_TexCoord;
 uniform vec2 in_Scaling;
+uniform mat4 in_rotationMatrix;
 
 out vec2 texCoord;
 
 void main()
 {
     texCoord = in_TexCoord;
-    gl_Position = vec4(in_Pos.x*in_Scaling.x, in_Pos.y*in_Scaling.y, 0.0, 1.0);
+    gl_Position = in_rotationMatrix * vec4(in_Pos.x*in_Scaling.x, in_Pos.y*in_Scaling.y, 0.0, 1.0);
 }
 )glsl";
 
@@ -42,23 +43,37 @@ static const GLchar* fShaderSrc = R"glsl(
 out vec4 fragColor;
 in vec2 texCoord;
 
-uniform sampler2D tex;
+uniform sampler2D tex_y, tex_uv;
 
 void main()
 {
-    fragColor = texture(tex, texCoord);
+    mediump vec3 yuv, rgb;
+    yuv.x = (texture(tex_y, texCoord).r);
+    yuv.yz = (texture(tex_uv, texCoord).rg - vec2(0.5, 0.5));
+    rgb = mat3( 1,       1,      1,
+                0, -0.3441, 1.7720,
+                1.4020, -0.7141, 0) * yuv;
+    fragColor = vec4(rgb, 1);
 }
 )glsl";
 
+@interface CallLayer()
+
+@property BOOL currentFrameDisplayed;
+@property NSLock* currentFrameLk;
+@property CGFloat currentWidth;
+@property CGFloat currentHeight;
+@property CGFloat currentAngle;
+@property CVPixelBufferRef currentFrame;
+
+@end
+
 @implementation CallLayer
 
 // OpenGL handlers
-GLuint tex, vbo, vShader, fShader, sProg, vao;
+GLuint textureY, textureUV, textureUniformY, textureUniformUV, vbo, vShader, fShader, sProg, vao;
 
-// Last frame data and attributes
-Video::Frame currentFrame;
-BOOL currentFrameDisplayed;
-NSLock* currentFrameLk;
+@synthesize currentAngle, currentFrameDisplayed, currentFrameLk, currentWidth, currentHeight, currentFrame, videoRunning;
 
 - (id) init
 {
@@ -113,6 +128,9 @@ NSLock* currentFrameLk;
         glLinkProgram(sProg);
         glUseProgram(sProg);
 
+        textureUniformY = glGetUniformLocation(sProg, "tex_y");
+        textureUniformUV = glGetUniformLocation(sProg, "tex_uv");
+
         // Vertices position attrib
         GLuint inPosAttrib = glGetAttribLocation(sProg, "in_Pos");
         glEnableVertexAttribArray(inPosAttrib);
@@ -122,10 +140,19 @@ NSLock* currentFrameLk;
         GLuint inTexCoordAttrib = glGetAttribLocation(sProg, "in_TexCoord");
         glEnableVertexAttribArray(inTexCoordAttrib);
         glVertexAttribPointer(inTexCoordAttrib, 2, GL_FLOAT, GL_FALSE, 4*sizeof(GLfloat), (void*)(2*sizeof(GLfloat)));
+        // TextureY
+        glActiveTexture(GL_TEXTURE0);
+        glGenTextures(1, &textureY);
+        glBindTexture(GL_TEXTURE_2D, textureY);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
 
-        // Texture
-        glGenTextures(1, &tex);
-        glBindTexture(GL_TEXTURE_2D, tex);
+        // TextureUV
+        glActiveTexture(GL_TEXTURE1);
+        glGenTextures(1, &textureUV);
+        glBindTexture(GL_TEXTURE_2D, textureUV);
         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
@@ -161,25 +188,35 @@ NSLock* currentFrameLk;
 - (void)drawInOpenGLContext:(NSOpenGLContext *)context pixelFormat:(NSOpenGLPixelFormat *)pixelFormat forLayerTime:(CFTimeInterval)t displayTime:(const CVTimeStamp *)ts
 {
     GLenum errEnum;
-    glBindTexture(GL_TEXTURE_2D, tex);
-
     [currentFrameLk lock];
-    if(!currentFrameDisplayed) {
-        if(currentFrame.ptr) {
-            glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, currentFrame.width, currentFrame.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, currentFrame.ptr);
-        }
+    if(!currentFrameDisplayed && currentFrame) {
+        CVPixelBufferLockBaseAddress(currentFrame, 0);
+        [self configureTexture:textureY
+                         index:0
+                       uniform:textureUniformY
+                 activeTexture:GL_TEXTURE0
+                        format:GL_RED
+                     fullPlane: YES];
+        [self configureTexture:textureUV
+                         index:1
+                       uniform:textureUniformUV
+                 activeTexture:GL_TEXTURE1
+                        format:GL_RG
+                     fullPlane: NO];
+        CVPixelBufferUnlockBaseAddress(currentFrame, 0);
+        CVPixelBufferRelease(currentFrame);
         currentFrameDisplayed = YES;
     }
     // To ensure that we will not divide by zero
-    if (currentFrame.ptr && currentFrame.width && currentFrame.height) {
+    if (currentFrame && currentWidth && currentHeight) {
         // Compute scaling factor to keep the original aspect ratio of the video
         CGSize viewSize = self.frame.size;
-        float viewRatio = viewSize.width/viewSize.height;
-        float frameRatio = ((float)currentFrame.width)/((float)currentFrame.height);
+        float viewRatio = (currentAngle == 90 || currentAngle == -90) ?
+           viewSize.height/viewSize.width : viewSize.width/viewSize.height;
+        float frameRatio = ((float)currentWidth)/((float)currentHeight);
         float ratio = viewRatio * (1/frameRatio);
 
         GLint inScalingUniform = glGetUniformLocation(sProg, "in_Scaling");
-
         float multiplier = MAX(frameRatio, ratio);
         if((viewRatio >= 1 && frameRatio >= 1) ||
            (viewRatio < 1 && frameRatio < 1) ||
@@ -193,24 +230,73 @@ NSLock* currentFrameLk;
                 glUniform2f(inScalingUniform, 1.0, 1.0 * ratio);
             else
                 glUniform2f(inScalingUniform, 1.0/ratio, 1.0);
-
         }
     }
-    [currentFrameLk unlock];
 
-    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
+    // apply rotation
+    float radians = (currentAngle * M_PI) / 180;
+    float rotation[16] =
+    {
+         cos(radians), -sin(radians), 0.0f, 0.0f,
+         sin(radians), cos(radians),  0.0f, 0.0f,
+         0.0f,         0.0f,          1.0f, 0.0f,
+         0.0f,         0.0f,          0.0f, 1.0f
+    };
+    GLint location = glGetUniformLocation(sProg, "in_rotationMatrix");
+    glUniformMatrix4fv(location, 1, GL_FALSE, rotation);
+
+    [currentFrameLk unlock];
+    glClearColor(0.0f, 0.0f, 0.0f, 0.1f);
     glClear(GL_COLOR_BUFFER_BIT);
 
     if([self videoRunning])
         glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
 }
 
-- (void) setCurrentFrame:(Video::Frame)framePtr
-{
+-(void)configureTexture:(GLuint)texture index:(int)index
+                uniform:(GLuint)uniform
+          activeTexture:(GLenum)activeTexture
+                 format:(GLint)format
+              fullPlane:(BOOL)fullPlane {
+    auto plane = CVPixelBufferGetBaseAddressOfPlane(currentFrame, index);
+    auto width = CVPixelBufferGetWidthOfPlane(currentFrame, index);
+    auto height = CVPixelBufferGetHeightOfPlane(currentFrame, index);
+    auto strideWidth = CVPixelBufferGetBytesPerRowOfPlane(currentFrame, index);
+    strideWidth = fullPlane ? strideWidth : strideWidth * 0.5;
+    if(strideWidth > width) {
+        glPixelStorei(GL_UNPACK_ROW_LENGTH, strideWidth);
+        glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+    } else {
+        glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
+        glPixelStorei(GL_UNPACK_ALIGNMENT, 0);
+    }
+    glActiveTexture(activeTexture);
+    glBindTexture(GL_TEXTURE_2D, texture);
+    glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, GL_UNSIGNED_BYTE, plane);
+    glUniform1i(uniform, index);
+}
+
+-(void)fillWithBlack {
     [currentFrameLk lock];
-    currentFrame = std::move(framePtr);
+    if(currentFrame) {
+        currentFrame = nullptr;
+        currentFrameDisplayed = YES;
+    }
+    [currentFrameLk unlock];
+}
+
+-(void)renderWithPixelBuffer:(CVPixelBufferRef)buffer size:(CGSize)size rotation: (float)rotation fillFrame: (bool)fill {
+    [currentFrameLk lock];
+    currentFrame = buffer;
+    CFRetain(currentFrame);
+    currentWidth = size.width;
+    currentHeight = size.height;
+    currentAngle = rotation;
     currentFrameDisplayed = NO;
+    videoRunning = YES;
     [currentFrameLk unlock];
 }
+-(void)setupView {
+}
 
 @end
diff --git a/src/views/CallMTKView.h b/src/views/CallMTKView.h
index edf09d57..ab432a43 100644
--- a/src/views/CallMTKView.h
+++ b/src/views/CallMTKView.h
@@ -19,10 +19,7 @@
 
 #import <Cocoa/Cocoa.h>
 #import <MetalKit/MetalKit.h>
+#import "VideoRendering.h"
 
-@interface CallMTKView: MTKView
--(void)renderWithPixelBuffer:(CVPixelBufferRef)buffer size:(CGSize)size rotation: (float)rotation fillFrame: (bool)fill;
--(void)fillWithBlack;
--(void)setupView;
-@property bool stopRendering;
+@interface CallMTKView: MTKView <VideoRendering>
 @end
diff --git a/src/views/CallMTKView.mm b/src/views/CallMTKView.mm
index b49dd466..98d0afca 100644
--- a/src/views/CallMTKView.mm
+++ b/src/views/CallMTKView.mm
@@ -48,6 +48,7 @@ struct Uniforms {
     simd::float4x4 projectionMatrix;
     simd::float4x4 rotationMatrix;
 };
+@synthesize videoRunning;
 
 - (instancetype)initWithFrame:(NSRect)frame
 {
@@ -151,7 +152,7 @@ bool frameDisplayed = false;
     if(frameDisplayed) {
         return;
     }
-    if(_stopRendering) {
+    if(!self.videoRunning) {
         self.releaseDrawables;
         return;
     }
diff --git a/src/views/RenderingView.h b/src/views/RenderingView.h
new file mode 100644
index 00000000..1be755f2
--- /dev/null
+++ b/src/views/RenderingView.h
@@ -0,0 +1,26 @@
+/*
+*  Copyright (C) 2020 Savoir-faire Linux Inc.
+*  Author: Kateryna Kostiuk <kateryna.kostiuk@savoirfairelinux.com>
+*
+*  This program is free software; you can redistribute it and/or modify
+*  it under the terms of the GNU General Public License as published by
+*  the Free Software Foundation; either version 3 of the License, or
+*  (at your option) any later version.
+*
+*  This program is distributed in the hope that it will be useful,
+*  but WITHOUT ANY WARRANTY; without even the implied warranty of
+*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+*  GNU General Public License for more details.
+*
+*  You should have received a copy of the GNU General Public License
+*  along with this program; if not, write to the Free Software
+*  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.
+*/
+
+#import <Cocoa/Cocoa.h>
+#import "VideoRendering.h"
+
+@interface RenderingView : NSView <VideoRendering>
+
+@end
+
diff --git a/src/views/RenderingView.mm b/src/views/RenderingView.mm
new file mode 100644
index 00000000..24d80064
--- /dev/null
+++ b/src/views/RenderingView.mm
@@ -0,0 +1,89 @@
+/*
+*  Copyright (C) 2020 Savoir-faire Linux Inc.
+*  Author: Kateryna Kostiuk <kateryna.kostiuk@savoirfairelinux.com>
+*
+*  This program is free software; you can redistribute it and/or modify
+*  it under the terms of the GNU General Public License as published by
+*  the Free Software Foundation; either version 3 of the License, or
+*  (at your option) any later version.
+*
+*  This program is distributed in the hope that it will be useful,
+*  but WITHOUT ANY WARRANTY; without even the implied warranty of
+*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+*  GNU General Public License for more details.
+*
+*  You should have received a copy of the GNU General Public License
+*  along with this program; if not, write to the Free Software
+*  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.
+*/
+#import "RenderingView.h"
+#import "src/utils.h"
+#import "CallMTKView.h"
+#import "CallLayer.h"
+
+@interface RenderingView()
+
+@property id <VideoRendering> renderer;
+
+@end
+
+@implementation RenderingView
+@synthesize videoRunning, renderer;
+
+- (instancetype)initWithFrame:(NSRect)frame {
+    self = [super initWithFrame:frame];
+    [self commonInit];
+    return self;
+}
+
+- (instancetype)initWithCoder:(NSCoder *)coder {
+    self = [super initWithCoder:coder];
+    [self commonInit];
+    return self;
+}
+
+-(void)commonInit {
+    if ([self metalSupported]) {
+        renderer = [[CallMTKView alloc] initWithFrame:self.frame];
+        NSView* renderView = (NSView*)renderer;
+        [self addSubview: renderView];
+        renderView.translatesAutoresizingMaskIntoConstraints = true;
+        [renderView setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
+        [renderView.topAnchor constraintEqualToAnchor:self.topAnchor constant:0].active = YES;
+        [renderView.bottomAnchor constraintEqualToAnchor:self.bottomAnchor constant:0].active = YES;
+        [renderView.leadingAnchor constraintEqualToAnchor:self.leadingAnchor constant:0].active = YES;
+        [renderView.trailingAnchor constraintEqualToAnchor:self.trailingAnchor constant:0].active = YES;
+    } else {
+        [self setLayer:[[CallLayer alloc] init]];
+        [self setWantsLayer:true];
+        CallLayer* callLayer = (CallLayer*)self.layer;
+        renderer = callLayer;
+    }
+}
+
+-(void)renderWithPixelBuffer:(CVPixelBufferRef)buffer size:(CGSize)size rotation: (float)rotation fillFrame: (bool)fill {
+    [renderer renderWithPixelBuffer:buffer size:size rotation:rotation fillFrame:fill];
+}
+
+-(void)fillWithBlack {
+    [renderer fillWithBlack];
+    [self.layer setBackgroundColor:NSColor.blackColor.CGColor];
+}
+
+-(void)setupView {
+    [renderer setupView];
+}
+
+-(void)setVideoRunning:(BOOL)running {
+    // for opengl video running set when new frame received
+    if ([self metalSupported] || !running) {
+        renderer.videoRunning = running;
+    }
+    videoRunning = running;
+}
+
+-(BOOL)metalSupported {
+    return MTLCreateSystemDefaultDevice() != nil;
+}
+
+@end
diff --git a/src/views/VideoRendering.h b/src/views/VideoRendering.h
new file mode 100644
index 00000000..cef76e7a
--- /dev/null
+++ b/src/views/VideoRendering.h
@@ -0,0 +1,29 @@
+/*
+*  Copyright (C) 2020 Savoir-faire Linux Inc.
+*  Author: Kateryna Kostiuk <kateryna.kostiuk@savoirfairelinux.com>
+*
+*  This program is free software; you can redistribute it and/or modify
+*  it under the terms of the GNU General Public License as published by
+*  the Free Software Foundation; either version 3 of the License, or
+*  (at your option) any later version.
+*
+*  This program is distributed in the hope that it will be useful,
+*  but WITHOUT ANY WARRANTY; without even the implied warranty of
+*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+*  GNU General Public License for more details.
+*
+*  You should have received a copy of the GNU General Public License
+*  along with this program; if not, write to the Free Software
+*  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.
+*/
+
+#import <Foundation/Foundation.h>
+#import <video/renderer.h>
+@protocol VideoRendering
+-(void)renderWithPixelBuffer:(CVPixelBufferRef)buffer size:(CGSize)size rotation: (float)rotation fillFrame: (bool)fill;
+-(void)fillWithBlack;
+-(void)setupView;
+@property BOOL videoRunning;
+
+@end
+
diff --git a/ui/Base.lproj/CurrentCall.xib b/ui/Base.lproj/CurrentCall.xib
index 92e85a5f..df09647e 100644
--- a/ui/Base.lproj/CurrentCall.xib
+++ b/ui/Base.lproj/CurrentCall.xib
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="14490.70" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
+<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="15705" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
     <dependencies>
-        <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="14490.70"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="15705"/>
         <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
     </dependencies>
     <objects>
@@ -19,6 +19,7 @@
                 <outlet property="contactPhoto" destination="z3E-kv-Uwb" id="otV-zW-LCQ"/>
                 <outlet property="controlsPanel" destination="wDi-X6-dgL" id="zs8-jw-wQ3"/>
                 <outlet property="controlsStackView" destination="Djs-L8-8Pe" id="Nsi-pe-3uh"/>
+                <outlet property="distantView" destination="gQE-fN-JhY" id="ARl-xd-Cfc"/>
                 <outlet property="hangUpButton" destination="Kjq-iM-NBL" id="Puz-4L-Okl"/>
                 <outlet property="headerContainer" destination="DfH-di-xs7" id="gAV-d7-fNh"/>
                 <outlet property="headerGradientView" destination="d0X-cW-Xgz" id="5l9-Sl-TSk"/>
@@ -31,11 +32,10 @@
                 <outlet property="muteAudioButton" destination="tQl-cT-0Lb" id="qV4-Ef-UTx"/>
                 <outlet property="muteVideoButton" destination="LVS-yZ-98V" id="qQs-zP-wQ4"/>
                 <outlet property="pickUpButton" destination="qgD-3D-nD5" id="eu2-aU-twv"/>
-                <outlet property="previewView" destination="6y6-RH-qOp" id="1PY-sd-mh4"/>
+                <outlet property="previewView" destination="6y6-RH-qOp" id="odr-bq-Wdg"/>
                 <outlet property="recordOnOffButton" destination="QYT-0n-4sw" id="LpC-8i-BGz"/>
                 <outlet property="splitView" destination="GIJ-gB-FZo" id="PM0-az-Q8X"/>
                 <outlet property="timeSpentLabel" destination="dl1-Gt-oz5" id="jdk-Ky-BG6"/>
-                <outlet property="videoMTKView" destination="gQE-fN-JhY" id="qca-wq-idt"/>
                 <outlet property="videoView" destination="2wf-Py-l6B" id="dEF-Gx-w6x"/>
                 <outlet property="view" destination="Hz6-mo-xeY" id="VKn-lN-ijP"/>
             </connections>
@@ -65,10 +65,10 @@
                                     <color key="fillColor" red="0.120510533452034" green="0.12050692737102509" blue="0.12050899863243103" alpha="1" colorSpace="calibratedRGB"/>
                                 </box>
                                 <stackView distribution="fill" orientation="vertical" alignment="centerX" spacing="10" horizontalStackHuggingPriority="249.99998474121094" verticalStackHuggingPriority="249.99998474121094" translatesAutoresizingMaskIntoConstraints="NO" id="aLB-LA-yn0">
-                                    <rect key="frame" x="302" y="249" width="142" height="308"/>
+                                    <rect key="frame" x="302" y="250" width="142" height="305"/>
                                     <subviews>
                                         <customView translatesAutoresizingMaskIntoConstraints="NO" id="s4L-Ke-9Jm">
-                                            <rect key="frame" x="7" y="180" width="128" height="128"/>
+                                            <rect key="frame" x="7" y="177" width="128" height="128"/>
                                             <subviews>
                                                 <imageView horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="z3E-kv-Uwb" userLabel="contactPhoto">
                                                     <rect key="frame" x="4" y="4" width="120" height="120"/>
@@ -96,7 +96,7 @@
                                             </constraints>
                                         </customView>
                                         <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Q9v-1a-PP9" userLabel="contactName">
-                                            <rect key="frame" x="12" y="148" width="118" height="22"/>
+                                            <rect key="frame" x="12" y="146" width="118" height="21"/>
                                             <constraints>
                                                 <constraint firstAttribute="width" relation="greaterThanOrEqual" constant="81" id="tvn-e9-GfK"/>
                                             </constraints>
@@ -107,7 +107,7 @@
                                             </textFieldCell>
                                         </textField>
                                         <textField verticalHuggingPriority="750" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Qq2-Et-gep" userLabel="contactID">
-                                            <rect key="frame" x="39" y="121" width="65" height="17"/>
+                                            <rect key="frame" x="39" y="120" width="65" height="16"/>
                                             <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" state="on" alignment="center" title="person Id" id="hKi-Ay-ex5">
                                                 <font key="font" metaFont="systemLight" size="13"/>
                                                 <color key="textColor" name="selectedMenuItemTextColor" catalog="System" colorSpace="catalog"/>
@@ -115,14 +115,14 @@
                                             </textFieldCell>
                                         </textField>
                                         <customView translatesAutoresizingMaskIntoConstraints="NO" id="Wps-oy-aXf">
-                                            <rect key="frame" x="69" y="106" width="5" height="5"/>
+                                            <rect key="frame" x="69" y="105" width="5" height="5"/>
                                             <constraints>
                                                 <constraint firstAttribute="height" constant="5" id="2gw-nj-4KM"/>
                                                 <constraint firstAttribute="width" constant="5" id="BNy-PR-qtu"/>
                                             </constraints>
                                         </customView>
                                         <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Ff6-F4-zbn" userLabel="callState">
-                                            <rect key="frame" x="50" y="78" width="42" height="18"/>
+                                            <rect key="frame" x="50" y="78" width="42" height="17"/>
                                             <constraints>
                                                 <constraint firstAttribute="width" relation="greaterThanOrEqual" constant="29" id="tka-qK-aZu"/>
                                             </constraints>
@@ -222,14 +222,14 @@
                                         <real value="3.4028234663852886e+38"/>
                                     </customSpacing>
                                 </stackView>
-                                <customView translatesAutoresizingMaskIntoConstraints="NO" id="gQE-fN-JhY" customClass="CallMTKView">
+                                <customView translatesAutoresizingMaskIntoConstraints="NO" id="gQE-fN-JhY" customClass="RenderingView">
                                     <rect key="frame" x="0.0" y="0.0" width="746" height="805"/>
                                 </customView>
                                 <customView translatesAutoresizingMaskIntoConstraints="NO" id="d0X-cW-Xgz" customClass="GradientView">
-                                    <rect key="frame" x="0.0" y="733" width="746" height="72"/>
+                                    <rect key="frame" x="0.0" y="734" width="746" height="71"/>
                                     <subviews>
                                         <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="cIU-M7-xpN">
-                                            <rect key="frame" x="624" y="24" width="104" height="24"/>
+                                            <rect key="frame" x="624" y="24" width="104" height="23"/>
                                             <constraints>
                                                 <constraint firstAttribute="width" constant="100" id="9vz-kb-6L6"/>
                                             </constraints>
@@ -285,7 +285,7 @@
                                     <rect key="frame" x="550" y="20" width="175" height="120"/>
                                     <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
                                     <subviews>
-                                        <customView autoresizesSubviews="NO" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="6y6-RH-qOp" userLabel="Preview" customClass="CallMTKView">
+                                        <customView autoresizesSubviews="NO" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="6y6-RH-qOp" userLabel="Preview" customClass="RenderingView">
                                             <rect key="frame" x="0.0" y="0.0" width="175" height="120"/>
                                             <autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" heightSizable="YES" flexibleMaxY="YES"/>
                                             <subviews>
@@ -321,10 +321,10 @@
                                     </subviews>
                                 </customView>
                                 <customView translatesAutoresizingMaskIntoConstraints="NO" id="DfH-di-xs7" customClass="GradientView">
-                                    <rect key="frame" x="0.0" y="733" width="746" height="72"/>
+                                    <rect key="frame" x="0.0" y="734" width="746" height="71"/>
                                     <subviews>
                                         <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="dl1-Gt-oz5">
-                                            <rect key="frame" x="624" y="24" width="104" height="24"/>
+                                            <rect key="frame" x="624" y="24" width="104" height="23"/>
                                             <constraints>
                                                 <constraint firstAttribute="width" constant="100" id="zSV-0S-PdC"/>
                                             </constraints>
@@ -683,7 +683,7 @@
                                                                             <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
                                                                             <subviews>
                                                                                 <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="IJm-DU-cs6">
-                                                                                    <rect key="frame" x="160" y="9" width="8" height="17"/>
+                                                                                    <rect key="frame" x="160" y="9" width="8" height="16"/>
                                                                                     <constraints>
                                                                                         <constraint firstAttribute="width" priority="250" constant="20" id="HNl-gc-YBr"/>
                                                                                     </constraints>
@@ -750,7 +750,7 @@
                                                                             <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
                                                                             <subviews>
                                                                                 <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="xkH-rw-k6w">
-                                                                                    <rect key="frame" x="160" y="9" width="8" height="17"/>
+                                                                                    <rect key="frame" x="160" y="9" width="8" height="16"/>
                                                                                     <constraints>
                                                                                         <constraint firstAttribute="width" priority="250" constant="20" id="IIf-Z3-Q3T"/>
                                                                                     </constraints>
@@ -806,7 +806,7 @@
                                                                             <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
                                                                             <subviews>
                                                                                 <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" tag="200" translatesAutoresizingMaskIntoConstraints="NO" id="SMB-Vk-E06">
-                                                                                    <rect key="frame" x="160" y="7" width="8" height="17"/>
+                                                                                    <rect key="frame" x="160" y="7" width="8" height="16"/>
                                                                                     <constraints>
                                                                                         <constraint firstAttribute="width" priority="250" constant="20" id="Wod-ib-NVj"/>
                                                                                     </constraints>
diff --git a/ui/Base.lproj/RecordFileVC.xib b/ui/Base.lproj/RecordFileVC.xib
index 82938aa8..39bcf0fb 100644
--- a/ui/Base.lproj/RecordFileVC.xib
+++ b/ui/Base.lproj/RecordFileVC.xib
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="14490.70" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
+<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="15705" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
     <dependencies>
-        <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="14490.70"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="15705"/>
         <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
     </dependencies>
     <objects>
@@ -26,11 +26,11 @@
             <rect key="frame" x="0.0" y="0.0" width="480" height="272"/>
             <autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" heightSizable="YES" flexibleMaxY="YES"/>
             <subviews>
-                <customView translatesAutoresizingMaskIntoConstraints="NO" id="rRf-Sm-dXA" customClass="CallMTKView">
+                <customView translatesAutoresizingMaskIntoConstraints="NO" id="rRf-Sm-dXA" customClass="RenderingView">
                     <rect key="frame" x="0.0" y="0.0" width="480" height="272"/>
                 </customView>
                 <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="MXV-85-UvC">
-                    <rect key="frame" x="165" y="73" width="151" height="17"/>
+                    <rect key="frame" x="165" y="73" width="151" height="16"/>
                     <textFieldCell key="cell" lineBreakMode="clipping" alignment="center" title="Press to start recording" id="Dp1-8c-of5">
                         <font key="font" usesAppearanceFont="YES"/>
                         <color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
@@ -54,7 +54,7 @@
                     </userDefinedRuntimeAttributes>
                 </button>
                 <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="ZjD-ni-kiA">
-                    <rect key="frame" x="238" y="124" width="4" height="24"/>
+                    <rect key="frame" x="238" y="125" width="4" height="23"/>
                     <textFieldCell key="cell" lineBreakMode="clipping" id="VXB-jT-wv2">
                         <font key="font" metaFont="system" size="20"/>
                         <color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
@@ -93,7 +93,7 @@
                     </connections>
                 </button>
                 <button hidden="YES" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="6Nv-0Z-3Lv">
-                    <rect key="frame" x="412" y="17" width="48" height="24"/>
+                    <rect key="frame" x="412" y="18" width="48" height="23"/>
                     <buttonCell key="cell" type="square" title="Send" bezelStyle="shadowlessSquare" alignment="center" inset="2" id="UXO-l1-POf">
                         <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
                         <font key="font" metaFont="system" size="20"/>
@@ -157,6 +157,7 @@
                 <constraint firstAttribute="trailing" secondItem="rRf-Sm-dXA" secondAttribute="trailing" id="r9d-DV-Kle"/>
                 <constraint firstItem="rRf-Sm-dXA" firstAttribute="top" secondItem="Hz6-mo-xeY" secondAttribute="top" id="vl5-VY-oXf"/>
             </constraints>
+            <point key="canvasLocation" x="139" y="154"/>
         </customView>
     </objects>
     <resources>
diff --git a/ui/Base.lproj/VideoPrefs.xib b/ui/Base.lproj/VideoPrefs.xib
index fe370b8d..5f8e44e8 100644
--- a/ui/Base.lproj/VideoPrefs.xib
+++ b/ui/Base.lproj/VideoPrefs.xib
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="15505" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
+<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="15705" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
     <dependencies>
-        <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="15505"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="15705"/>
         <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
     </dependencies>
     <objects>
@@ -48,7 +48,7 @@
                                                     </constraints>
                                                     <popUpButtonCell key="cell" type="push" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" borderStyle="borderAndBezel" imageScaling="proportionallyDown" inset="2" id="6Vf-hb-26C">
                                                         <behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
-                                                        <font key="font" metaFont="system"/>
+                                                        <font key="font" metaFont="menu"/>
                                                         <menu key="menu" id="zJ9-1a-cpr">
                                                             <connections>
                                                                 <outlet property="delegate" destination="-2" id="mF2-Zc-wNP"/>
@@ -87,7 +87,7 @@
                                                     </constraints>
                                                     <popUpButtonCell key="cell" type="push" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" borderStyle="borderAndBezel" imageScaling="proportionallyDown" inset="2" id="6ly-dX-MT4">
                                                         <behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
-                                                        <font key="font" metaFont="system"/>
+                                                        <font key="font" metaFont="menu"/>
                                                         <menu key="menu" id="ykd-50-las">
                                                             <connections>
                                                                 <outlet property="delegate" destination="-2" id="5cI-wH-0AT"/>
@@ -126,7 +126,7 @@
                                                     </constraints>
                                                     <popUpButtonCell key="cell" type="push" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" borderStyle="borderAndBezel" imageScaling="proportionallyDown" inset="2" id="pDt-c4-Fhs">
                                                         <behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
-                                                        <font key="font" metaFont="system"/>
+                                                        <font key="font" metaFont="menu"/>
                                                         <menu key="menu" id="aKL-76-vSP">
                                                             <connections>
                                                                 <outlet property="delegate" destination="-2" id="5Gu-bg-y3C"/>
@@ -190,7 +190,7 @@
                                 <real value="3.4028234663852886e+38"/>
                             </customSpacing>
                         </stackView>
-                        <customView wantsLayer="YES" canDrawConcurrently="YES" translatesAutoresizingMaskIntoConstraints="NO" id="qAJ-w8-a6Q" userLabel="Preview" customClass="CallMTKView">
+                        <customView wantsLayer="YES" canDrawConcurrently="YES" translatesAutoresizingMaskIntoConstraints="NO" id="qAJ-w8-a6Q" userLabel="Preview" customClass="RenderingView">
                             <rect key="frame" x="0.0" y="0.0" width="470" height="256"/>
                             <constraints>
                                 <constraint firstAttribute="width" constant="470" id="ipm-Al-OAC"/>
-- 
GitLab