blob: ad4903a90f6108ea41b431fc9b60ccf5a48b1d73 [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;
denicijad2088152017-04-28 02:14:54 -070032@property(nonatomic, strong) id rendererNV12Mock;
33@property(nonatomic, strong) id rendererI420Mock;
34@property(nonatomic, strong) id frameMock;
kthelgason954d9b92017-03-09 03:36:58 -080035@end
36
37@implementation RTCMTLVideoViewTests
38
39@synthesize classMock = _classMock;
denicijad2088152017-04-28 02:14:54 -070040@synthesize rendererNV12Mock = _rendererNV12Mock;
41@synthesize rendererI420Mock = _rendererI420Mock;
42@synthesize frameMock = _frameMock;
kthelgason954d9b92017-03-09 03:36:58 -080043
44- (void)setup {
45 self.classMock = OCMClassMock([RTCMTLVideoView class]);
Danielac548aab2017-10-05 14:16:38 +020046 [self startMockingNilView];
kthelgason954d9b92017-03-09 03:36:58 -080047}
48
49- (void)tearDown {
50 [self.classMock stopMocking];
denicijad2088152017-04-28 02:14:54 -070051 [self.rendererI420Mock stopMocking];
52 [self.rendererNV12Mock stopMocking];
denicijad2088152017-04-28 02:14:54 -070053 [self.frameMock stopMocking];
kthelgason954d9b92017-03-09 03:36:58 -080054 self.classMock = nil;
denicijad2088152017-04-28 02:14:54 -070055 self.rendererI420Mock = nil;
56 self.rendererNV12Mock = nil;
denicijad2088152017-04-28 02:14:54 -070057 self.frameMock = nil;
kthelgason954d9b92017-03-09 03:36:58 -080058}
59
Anders Carlssone5960ce2017-06-22 15:26:30 +020060- (id)frameMockWithCVPixelBuffer:(BOOL)hasCVPixelBuffer {
denicijad2088152017-04-28 02:14:54 -070061 id frameMock = OCMClassMock([RTCVideoFrame class]);
Anders Carlssone5960ce2017-06-22 15:26:30 +020062 if (hasCVPixelBuffer) {
63 CVPixelBufferRef pixelBufferRef;
64 CVPixelBufferCreate(kCFAllocatorDefault,
65 200,
66 200,
67 kCVPixelFormatType_420YpCbCr8Planar,
68 nullptr,
69 &pixelBufferRef);
70 OCMStub([frameMock buffer])
71 .andReturn([[RTCCVPixelBuffer alloc] initWithPixelBuffer:pixelBufferRef]);
denicijad2088152017-04-28 02:14:54 -070072 } else {
Anders Carlssone5960ce2017-06-22 15:26:30 +020073 OCMStub([frameMock buffer]).andReturn([[RTCI420Buffer alloc] initWithWidth:200 height:200]);
denicijad2088152017-04-28 02:14:54 -070074 }
75 return frameMock;
kthelgason954d9b92017-03-09 03:36:58 -080076}
77
denicijad2088152017-04-28 02:14:54 -070078- (id)rendererMockWithSuccessfulSetup:(BOOL)sucess {
79 id rendererMock = OCMProtocolMock(@protocol(RTCMTLRenderer));
80 OCMStub([rendererMock addRenderingDestination:[OCMArg any]]).andReturn(sucess);
kthelgason954d9b92017-03-09 03:36:58 -080081
denicijad2088152017-04-28 02:14:54 -070082 return rendererMock;
kthelgason954d9b92017-03-09 03:36:58 -080083}
84
Danielac548aab2017-10-05 14:16:38 +020085- (void)startMockingNilView {
86 // Use OCMock 2 syntax here until OCMock is upgraded to 3.4
87 [[[self.classMock stub] andReturn:nil] createMetalView:CGRectZero];
88}
89
denicijad2088152017-04-28 02:14:54 -070090#pragma mark - Test cases
91- (void)testInitAssertsIfMetalUnavailabe {
kthelgason954d9b92017-03-09 03:36:58 -080092 // given
93 OCMStub([self.classMock isMetalAvailable]).andReturn(NO);
kthelgason954d9b92017-03-09 03:36:58 -080094
95 // when
denicijad2088152017-04-28 02:14:54 -070096 BOOL asserts = NO;
97 @try {
98 RTCMTLVideoView *realView = [[RTCMTLVideoView alloc] initWithFrame:CGRectZero];
99 (void)realView;
100 } @catch (NSException *ex) {
101 asserts = YES;
102 }
kthelgason954d9b92017-03-09 03:36:58 -0800103
denicijad2088152017-04-28 02:14:54 -0700104 EXPECT_TRUE(asserts);
kthelgason954d9b92017-03-09 03:36:58 -0800105}
106
107- (void)testRTCVideoRenderNilFrameCallback {
108 // given
denicijad2088152017-04-28 02:14:54 -0700109 OCMStub([self.classMock isMetalAvailable]).andReturn(YES);
Danielac548aab2017-10-05 14:16:38 +0200110
kthelgason954d9b92017-03-09 03:36:58 -0800111 RTCMTLVideoView *realView = [[RTCMTLVideoView alloc] init];
denicijad2088152017-04-28 02:14:54 -0700112 self.frameMock = OCMClassMock([RTCVideoFrame class]);
113
Anders Carlssone5960ce2017-06-22 15:26:30 +0200114 [[self.frameMock reject] buffer];
denicijad2088152017-04-28 02:14:54 -0700115 [[self.classMock reject] createNV12Renderer];
116 [[self.classMock reject] createI420Renderer];
kthelgason954d9b92017-03-09 03:36:58 -0800117
118 // when
119 [realView renderFrame:nil];
Danielac548aab2017-10-05 14:16:38 +0200120 [realView drawInMTKView:nil];
kthelgason954d9b92017-03-09 03:36:58 -0800121
122 // then
denicijad2088152017-04-28 02:14:54 -0700123 [self.frameMock verify];
124 [self.classMock verify];
125}
126
127- (void)testRTCVideoRenderFrameCallbackI420 {
128 // given
129 OCMStub([self.classMock isMetalAvailable]).andReturn(YES);
130 self.rendererI420Mock = [self rendererMockWithSuccessfulSetup:YES];
Anders Carlssone5960ce2017-06-22 15:26:30 +0200131 self.frameMock = [self frameMockWithCVPixelBuffer:NO];
denicijad2088152017-04-28 02:14:54 -0700132
133 OCMExpect([self.rendererI420Mock drawFrame:self.frameMock]);
134 OCMExpect([self.classMock createI420Renderer]).andReturn(self.rendererI420Mock);
135 [[self.classMock reject] createNV12Renderer];
136
137 RTCMTLVideoView *realView = [[RTCMTLVideoView alloc] init];
138
139 // when
140 [realView renderFrame:self.frameMock];
Danielac548aab2017-10-05 14:16:38 +0200141 [realView drawInMTKView:nil];
denicijad2088152017-04-28 02:14:54 -0700142
143 // then
144 [self.rendererI420Mock verify];
145 [self.classMock verify];
146}
147
148- (void)testRTCVideoRenderFrameCallbackNV12 {
149 // given
150 OCMStub([self.classMock isMetalAvailable]).andReturn(YES);
151 self.rendererNV12Mock = [self rendererMockWithSuccessfulSetup:YES];
Anders Carlssone5960ce2017-06-22 15:26:30 +0200152 self.frameMock = [self frameMockWithCVPixelBuffer:YES];
denicijad2088152017-04-28 02:14:54 -0700153
154 OCMExpect([self.rendererNV12Mock drawFrame:self.frameMock]);
155 OCMExpect([self.classMock createNV12Renderer]).andReturn(self.rendererNV12Mock);
156 [[self.classMock reject] createI420Renderer];
157
158 RTCMTLVideoView *realView = [[RTCMTLVideoView alloc] init];
159
160 // when
161 [realView renderFrame:self.frameMock];
Danielac548aab2017-10-05 14:16:38 +0200162 [realView drawInMTKView:nil];
denicijad2088152017-04-28 02:14:54 -0700163
164 // then
165 [self.rendererNV12Mock verify];
166 [self.classMock verify];
kthelgason954d9b92017-03-09 03:36:58 -0800167}
168@end
169
denicijad2088152017-04-28 02:14:54 -0700170TEST(RTCMTLVideoViewTests, InitAssertsIfMetalUnavailabe) {
kthelgason954d9b92017-03-09 03:36:58 -0800171 RTCMTLVideoViewTests *test = [[RTCMTLVideoViewTests alloc] init];
172 [test setup];
kthelgason954d9b92017-03-09 03:36:58 -0800173
denicijad2088152017-04-28 02:14:54 -0700174 [test testInitAssertsIfMetalUnavailabe];
kthelgason954d9b92017-03-09 03:36:58 -0800175 [test tearDown];
176}
177
178TEST(RTCMTLVideoViewTests, RTCVideoRenderNilFrameCallback) {
179 RTCMTLVideoViewTests *test = [[RTCMTLVideoViewTests alloc] init];
180 [test setup];
181 [test testRTCVideoRenderNilFrameCallback];
182 [test tearDown];
183}
184
denicijad2088152017-04-28 02:14:54 -0700185TEST(RTCMTLVideoViewTests, RTCVideoRenderFrameCallbackI420) {
kthelgason954d9b92017-03-09 03:36:58 -0800186 RTCMTLVideoViewTests *test = [[RTCMTLVideoViewTests alloc] init];
187 [test setup];
denicijad2088152017-04-28 02:14:54 -0700188
189 [test testRTCVideoRenderFrameCallbackI420];
190 [test tearDown];
191}
192
magjed587ff112017-06-26 03:11:51 -0700193TEST(RTCMTLVideoViewTests, RTCVideoRenderFrameCallbackNV12) {
denicijad2088152017-04-28 02:14:54 -0700194 RTCMTLVideoViewTests *test = [[RTCMTLVideoViewTests alloc] init];
195 [test setup];
196
197 [test testRTCVideoRenderFrameCallbackNV12];
kthelgason954d9b92017-03-09 03:36:58 -0800198 [test tearDown];
199}