@@ -51,6 +51,14 @@ @implementation RTC_OBJC_TYPE (RTCMTLVideoView)
5151@synthesize lastFrameTimeNs = _lastFrameTimeNs;
5252@synthesize rotationOverride = _rotationOverride;
5353
54+ + (BOOL )isMetalAvailable {
55+ #if TARGET_OS_IPHONE
56+ return MTLCreateSystemDefaultDevice () != nil ;
57+ #elif TARGET_OS_OSX
58+ return [MTLCopyAllDevices () count ] > 0 ;
59+ #endif
60+ }
61+
5462- (instancetype )initWithFrame : (CGRect)frameRect {
5563 self = [super initWithFrame: frameRect];
5664 if (self) {
@@ -75,20 +83,18 @@ - (void)setEnabled:(BOOL)enabled {
7583 self.metalView .paused = !enabled;
7684}
7785
86+ #if TARGET_OS_IPHONE
7887- (UIViewContentMode)videoContentMode {
7988 return self.metalView .contentMode ;
8089}
8190
8291- (void )setVideoContentMode : (UIViewContentMode)mode {
8392 self.metalView .contentMode = mode;
8493}
94+ #endif
8595
8696#pragma mark - Private
8797
88- + (BOOL )isMetalAvailable {
89- return MTLCreateSystemDefaultDevice () != nil ;
90- }
91-
9298+ (MTKView *)createMetalView : (CGRect)frame {
9399 return [[MTKViewClass alloc ] initWithFrame: frame];
94100}
@@ -102,7 +108,7 @@ + (RTCMTLI420Renderer *)createI420Renderer {
102108}
103109
104110+ (RTCMTLRGBRenderer *)createRGBRenderer {
105- return [[RTCMTLRGBRenderer alloc ] init ];
111+ return [[RTCMTLRGBRendererClass alloc ] init ];
106112}
107113
108114- (void )configure {
@@ -111,19 +117,24 @@ - (void)configure {
111117
112118 self.metalView = [RTC_OBJC_TYPE (RTCMTLVideoView) createMetalView: self .bounds];
113119 self.metalView .delegate = self;
120+ #if TARGET_OS_IPHONE
114121 self.metalView .contentMode = UIViewContentModeScaleAspectFill;
122+ #elif TARGET_OS_OSX
123+ self.metalView .layerContentsPlacement = NSViewLayerContentsPlacementScaleProportionallyToFit;
124+ #endif
125+
115126 [self addSubview: self .metalView];
116127 self.videoFrameSize = CGSizeZero;
117128}
118129
130+ #if TARGET_OS_IPHONE
119131- (void )setMultipleTouchEnabled : (BOOL )multipleTouchEnabled {
120- [super setMultipleTouchEnabled: multipleTouchEnabled];
121- self.metalView .multipleTouchEnabled = multipleTouchEnabled;
132+ [super setMultipleTouchEnabled: multipleTouchEnabled];
133+ self.metalView .multipleTouchEnabled = multipleTouchEnabled;
122134}
135+ #endif
123136
124- - (void )layoutSubviews {
125- [super layoutSubviews ];
126-
137+ - (void )performLayout {
127138 CGRect bounds = self.bounds ;
128139 self.metalView .frame = bounds;
129140 if (!CGSizeEqualToSize (self.videoFrameSize , CGSizeZero)) {
@@ -203,10 +214,10 @@ - (void)setRotationOverride:(NSValue *)rotationOverride {
203214 [self setNeedsLayout ];
204215}
205216
206- - (RTCVideoRotation)frameRotation {
217+ - (RTCVideoRotation)videoRotation {
207218 if (self.rotationOverride ) {
208219 RTCVideoRotation rotation;
209- if (@available (iOS 11 , *)) {
220+ if (@available (iOS 11 , macos 10.13 , *)) {
210221 [self .rotationOverride getValue: &rotation size: sizeof (rotation)];
211222 } else {
212223 [self .rotationOverride getValue: &rotation];
@@ -220,10 +231,10 @@ - (RTCVideoRotation)frameRotation {
220231- (CGSize)drawableSize {
221232 // Flip width/height if the rotations are not the same.
222233 CGSize videoFrameSize = self.videoFrameSize ;
223- RTCVideoRotation frameRotation = [self frameRotation ];
234+ RTCVideoRotation videoRotation = [self videoRotation ];
224235
225236 BOOL useLandscape =
226- (frameRotation == RTCVideoRotation_0) || (frameRotation == RTCVideoRotation_180);
237+ (videoRotation == RTCVideoRotation_0) || (videoRotation == RTCVideoRotation_180);
227238 BOOL sizeIsLandscape = (self.videoFrame .rotation == RTCVideoRotation_0) ||
228239 (self.videoFrame .rotation == RTCVideoRotation_180);
229240
@@ -259,7 +270,37 @@ - (void)renderFrame:(nullable RTC_OBJC_TYPE(RTCVideoFrame) *)frame {
259270 RTCLogInfo (@" Incoming frame is nil. Exiting render callback." );
260271 return ;
261272 }
273+
274+ #if TARGET_OS_IPHONE
262275 self.videoFrame = frame;
276+ #elif TARGET_OS_OSX
277+ // Rendering native CVPixelBuffer is not supported on OS X.
278+ BOOL useI420 = NO ;
279+ if ([frame.buffer isKindOfClass: [RTC_OBJC_TYPE (RTCCVPixelBuffer) class ]]) {
280+ RTC_OBJC_TYPE (RTCCVPixelBuffer) *buffer = (RTC_OBJC_TYPE (RTCCVPixelBuffer) *)frame.buffer ;
281+ const OSType pixelFormat = CVPixelBufferGetPixelFormatType (buffer.pixelBuffer );
282+ useI420 = pixelFormat == kCVPixelFormatType_32BGRA || pixelFormat == kCVPixelFormatType_32ARGB ;
283+ }
284+ self.videoFrame = useI420 ? [frame newI420VideoFrame ] : frame;
285+ #endif
286+ }
287+
288+ #pragma mark - Cross platform
289+
290+ #if TARGET_OS_IPHONE
291+ - (void )layoutSubviews {
292+ [super layoutSubviews ];
293+ [self performLayout ];
294+ }
295+ #elif TARGET_OS_OSX
296+ - (void )layout {
297+ [super layout ];
298+ [self performLayout ];
299+ }
300+
301+ - (void )setNeedsLayout {
302+ self.needsLayout = YES ;
263303}
304+ #endif
264305
265306@end
0 commit comments