blob: eaaa71bd9ec99bb18bf344cb12c2c1a98c37a781 [file] [log] [blame]
kthelgason954d9b92017-03-09 03:36:58 -08001/*
2 * Copyright 2017 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11#import <Foundation/Foundation.h>
12#import <OCMock/OCMock.h>
13
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020014#include "rtc_base/gunit.h"
kthelgason954d9b92017-03-09 03:36:58 -080015
16#include <Metal/RTCMTLNV12Renderer.h>
17#include <WebRTC/RTCMTLVideoView.h>
Anders Carlssone5960ce2017-06-22 15:26:30 +020018#include <WebRTC/RTCVideoFrameBuffer.h>
kthelgason954d9b92017-03-09 03:36:58 -080019
20// Extension of RTCMTLVideoView for testing purposes.
21@interface RTCMTLVideoView (Testing)
kthelgason954d9b92017-03-09 03:36:58 -080022
23+ (BOOL)isMetalAvailable;
24+ (UIView*)createMetalView:(CGRect)frame;
denicijad2088152017-04-28 02:14:54 -070025+ (id<RTCMTLRenderer>)createNV12Renderer;
26+ (id<RTCMTLRenderer>)createI420Renderer;
kthelgason954d9b92017-03-09 03:36:58 -080027- (void)drawInMTKView:(id)view;
28@end
29
30@interface RTCMTLVideoViewTests : NSObject
31@property(nonatomic, strong) id classMock;
32@property(nonatomic, strong) id metalViewMock;
denicijad2088152017-04-28 02:14:54 -070033@property(nonatomic, strong) id rendererNV12Mock;
34@property(nonatomic, strong) id rendererI420Mock;
35@property(nonatomic, strong) id frameMock;
kthelgason954d9b92017-03-09 03:36:58 -080036@end
37
38@implementation RTCMTLVideoViewTests
39
40@synthesize classMock = _classMock;
41@synthesize metalViewMock = _metalViewMock;
denicijad2088152017-04-28 02:14:54 -070042@synthesize rendererNV12Mock = _rendererNV12Mock;
43@synthesize rendererI420Mock = _rendererI420Mock;
44@synthesize frameMock = _frameMock;
kthelgason954d9b92017-03-09 03:36:58 -080045
46- (void)setup {
47 self.classMock = OCMClassMock([RTCMTLVideoView class]);
kthelgason954d9b92017-03-09 03:36:58 -080048}
49
50- (void)tearDown {
51 [self.classMock stopMocking];
denicijad2088152017-04-28 02:14:54 -070052 [self.rendererI420Mock stopMocking];
53 [self.rendererNV12Mock stopMocking];
kthelgason954d9b92017-03-09 03:36:58 -080054 [self.metalViewMock stopMocking];
denicijad2088152017-04-28 02:14:54 -070055 [self.frameMock stopMocking];
kthelgason954d9b92017-03-09 03:36:58 -080056 self.classMock = nil;
denicijad2088152017-04-28 02:14:54 -070057 self.rendererI420Mock = nil;
58 self.rendererNV12Mock = nil;
kthelgason954d9b92017-03-09 03:36:58 -080059 self.metalViewMock = nil;
denicijad2088152017-04-28 02:14:54 -070060 self.frameMock = nil;
kthelgason954d9b92017-03-09 03:36:58 -080061}
62
Anders Carlssone5960ce2017-06-22 15:26:30 +020063- (id)frameMockWithCVPixelBuffer:(BOOL)hasCVPixelBuffer {
denicijad2088152017-04-28 02:14:54 -070064 id frameMock = OCMClassMock([RTCVideoFrame class]);
Anders Carlssone5960ce2017-06-22 15:26:30 +020065 if (hasCVPixelBuffer) {
66 CVPixelBufferRef pixelBufferRef;
67 CVPixelBufferCreate(kCFAllocatorDefault,
68 200,
69 200,
70 kCVPixelFormatType_420YpCbCr8Planar,
71 nullptr,
72 &pixelBufferRef);
73 OCMStub([frameMock buffer])
74 .andReturn([[RTCCVPixelBuffer alloc] initWithPixelBuffer:pixelBufferRef]);
denicijad2088152017-04-28 02:14:54 -070075 } else {
Anders Carlssone5960ce2017-06-22 15:26:30 +020076 OCMStub([frameMock buffer]).andReturn([[RTCI420Buffer alloc] initWithWidth:200 height:200]);
denicijad2088152017-04-28 02:14:54 -070077 }
78 return frameMock;
kthelgason954d9b92017-03-09 03:36:58 -080079}
80
denicijad2088152017-04-28 02:14:54 -070081- (id)rendererMockWithSuccessfulSetup:(BOOL)sucess {
82 id rendererMock = OCMProtocolMock(@protocol(RTCMTLRenderer));
83 OCMStub([rendererMock addRenderingDestination:[OCMArg any]]).andReturn(sucess);
kthelgason954d9b92017-03-09 03:36:58 -080084
denicijad2088152017-04-28 02:14:54 -070085 return rendererMock;
kthelgason954d9b92017-03-09 03:36:58 -080086}
87
denicijad2088152017-04-28 02:14:54 -070088#pragma mark - Test cases
89- (void)testInitAssertsIfMetalUnavailabe {
kthelgason954d9b92017-03-09 03:36:58 -080090 // given
91 OCMStub([self.classMock isMetalAvailable]).andReturn(NO);
kthelgason954d9b92017-03-09 03:36:58 -080092
93 // when
denicijad2088152017-04-28 02:14:54 -070094 BOOL asserts = NO;
95 @try {
96 RTCMTLVideoView *realView = [[RTCMTLVideoView alloc] initWithFrame:CGRectZero];
97 (void)realView;
98 } @catch (NSException *ex) {
99 asserts = YES;
100 }
kthelgason954d9b92017-03-09 03:36:58 -0800101
denicijad2088152017-04-28 02:14:54 -0700102 EXPECT_TRUE(asserts);
kthelgason954d9b92017-03-09 03:36:58 -0800103}
104
105- (void)testRTCVideoRenderNilFrameCallback {
106 // given
denicijad2088152017-04-28 02:14:54 -0700107 OCMStub([self.classMock isMetalAvailable]).andReturn(YES);
kthelgason954d9b92017-03-09 03:36:58 -0800108 RTCMTLVideoView *realView = [[RTCMTLVideoView alloc] init];
denicijad2088152017-04-28 02:14:54 -0700109 self.frameMock = OCMClassMock([RTCVideoFrame class]);
110
Anders Carlssone5960ce2017-06-22 15:26:30 +0200111 [[self.frameMock reject] buffer];
denicijad2088152017-04-28 02:14:54 -0700112 [[self.classMock reject] createNV12Renderer];
113 [[self.classMock reject] createI420Renderer];
kthelgason954d9b92017-03-09 03:36:58 -0800114
115 // when
116 [realView renderFrame:nil];
kthelgason954d9b92017-03-09 03:36:58 -0800117 [realView drawInMTKView:self.metalViewMock];
118
119 // then
denicijad2088152017-04-28 02:14:54 -0700120 [self.frameMock verify];
121 [self.classMock verify];
122}
123
124- (void)testRTCVideoRenderFrameCallbackI420 {
125 // given
126 OCMStub([self.classMock isMetalAvailable]).andReturn(YES);
127 self.rendererI420Mock = [self rendererMockWithSuccessfulSetup:YES];
Anders Carlssone5960ce2017-06-22 15:26:30 +0200128 self.frameMock = [self frameMockWithCVPixelBuffer:NO];
denicijad2088152017-04-28 02:14:54 -0700129
130 OCMExpect([self.rendererI420Mock drawFrame:self.frameMock]);
131 OCMExpect([self.classMock createI420Renderer]).andReturn(self.rendererI420Mock);
132 [[self.classMock reject] createNV12Renderer];
133
134 RTCMTLVideoView *realView = [[RTCMTLVideoView alloc] init];
135
136 // when
137 [realView renderFrame:self.frameMock];
138 [realView drawInMTKView:self.metalViewMock];
139
140 // then
141 [self.rendererI420Mock verify];
142 [self.classMock verify];
143}
144
145- (void)testRTCVideoRenderFrameCallbackNV12 {
146 // given
147 OCMStub([self.classMock isMetalAvailable]).andReturn(YES);
148 self.rendererNV12Mock = [self rendererMockWithSuccessfulSetup:YES];
Anders Carlssone5960ce2017-06-22 15:26:30 +0200149 self.frameMock = [self frameMockWithCVPixelBuffer:YES];
denicijad2088152017-04-28 02:14:54 -0700150
151 OCMExpect([self.rendererNV12Mock drawFrame:self.frameMock]);
152 OCMExpect([self.classMock createNV12Renderer]).andReturn(self.rendererNV12Mock);
153 [[self.classMock reject] createI420Renderer];
154
155 RTCMTLVideoView *realView = [[RTCMTLVideoView alloc] init];
156
157 // when
158 [realView renderFrame:self.frameMock];
159 [realView drawInMTKView:self.metalViewMock];
160
161 // then
162 [self.rendererNV12Mock verify];
163 [self.classMock verify];
kthelgason954d9b92017-03-09 03:36:58 -0800164}
165@end
166
denicijad2088152017-04-28 02:14:54 -0700167TEST(RTCMTLVideoViewTests, InitAssertsIfMetalUnavailabe) {
kthelgason954d9b92017-03-09 03:36:58 -0800168 RTCMTLVideoViewTests *test = [[RTCMTLVideoViewTests alloc] init];
169 [test setup];
kthelgason954d9b92017-03-09 03:36:58 -0800170
denicijad2088152017-04-28 02:14:54 -0700171 [test testInitAssertsIfMetalUnavailabe];
kthelgason954d9b92017-03-09 03:36:58 -0800172 [test tearDown];
173}
174
175TEST(RTCMTLVideoViewTests, RTCVideoRenderNilFrameCallback) {
176 RTCMTLVideoViewTests *test = [[RTCMTLVideoViewTests alloc] init];
177 [test setup];
178 [test testRTCVideoRenderNilFrameCallback];
179 [test tearDown];
180}
181
denicijad2088152017-04-28 02:14:54 -0700182TEST(RTCMTLVideoViewTests, RTCVideoRenderFrameCallbackI420) {
kthelgason954d9b92017-03-09 03:36:58 -0800183 RTCMTLVideoViewTests *test = [[RTCMTLVideoViewTests alloc] init];
184 [test setup];
denicijad2088152017-04-28 02:14:54 -0700185
186 [test testRTCVideoRenderFrameCallbackI420];
187 [test tearDown];
188}
189
magjed587ff112017-06-26 03:11:51 -0700190TEST(RTCMTLVideoViewTests, RTCVideoRenderFrameCallbackNV12) {
denicijad2088152017-04-28 02:14:54 -0700191 RTCMTLVideoViewTests *test = [[RTCMTLVideoViewTests alloc] init];
192 [test setup];
193
194 [test testRTCVideoRenderFrameCallbackNV12];
kthelgason954d9b92017-03-09 03:36:58 -0800195 [test tearDown];
196}