blob: 3743326cdc3dc0bc342c73f27a7f416af6321be8 [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
14#include "webrtc/base/gunit.h"
15
16#include <Metal/RTCMTLNV12Renderer.h>
17#include <WebRTC/RTCMTLVideoView.h>
Anders Carlsson75833902017-06-21 10:53:19 +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 Carlsson75833902017-06-21 10:53:19 +020063- (id)frameMockWithCVPixelBuffer:(BOOL)hasCVPixelBuffer {
denicijad2088152017-04-28 02:14:54 -070064 id frameMock = OCMClassMock([RTCVideoFrame class]);
Anders Carlsson75833902017-06-21 10:53:19 +020065 if (hasCVPixelBuffer) {
66 OCMStub([frameMock buffer])
67 .andReturn(
68 [[RTCCVPixelBuffer alloc] initWithPixelBuffer:(CVPixelBufferRef)[OCMArg anyPointer]]);
denicijad2088152017-04-28 02:14:54 -070069 } else {
Anders Carlsson75833902017-06-21 10:53:19 +020070 OCMStub([frameMock buffer]).andReturn([[RTCI420Buffer alloc] initWithWidth:200 height:200]);
denicijad2088152017-04-28 02:14:54 -070071 }
72 return frameMock;
kthelgason954d9b92017-03-09 03:36:58 -080073}
74
denicijad2088152017-04-28 02:14:54 -070075- (id)rendererMockWithSuccessfulSetup:(BOOL)sucess {
76 id rendererMock = OCMProtocolMock(@protocol(RTCMTLRenderer));
77 OCMStub([rendererMock addRenderingDestination:[OCMArg any]]).andReturn(sucess);
kthelgason954d9b92017-03-09 03:36:58 -080078
denicijad2088152017-04-28 02:14:54 -070079 return rendererMock;
kthelgason954d9b92017-03-09 03:36:58 -080080}
81
denicijad2088152017-04-28 02:14:54 -070082#pragma mark - Test cases
83- (void)testInitAssertsIfMetalUnavailabe {
kthelgason954d9b92017-03-09 03:36:58 -080084 // given
85 OCMStub([self.classMock isMetalAvailable]).andReturn(NO);
kthelgason954d9b92017-03-09 03:36:58 -080086
87 // when
denicijad2088152017-04-28 02:14:54 -070088 BOOL asserts = NO;
89 @try {
90 RTCMTLVideoView *realView = [[RTCMTLVideoView alloc] initWithFrame:CGRectZero];
91 (void)realView;
92 } @catch (NSException *ex) {
93 asserts = YES;
94 }
kthelgason954d9b92017-03-09 03:36:58 -080095
denicijad2088152017-04-28 02:14:54 -070096 EXPECT_TRUE(asserts);
kthelgason954d9b92017-03-09 03:36:58 -080097}
98
99- (void)testRTCVideoRenderNilFrameCallback {
100 // given
denicijad2088152017-04-28 02:14:54 -0700101 OCMStub([self.classMock isMetalAvailable]).andReturn(YES);
kthelgason954d9b92017-03-09 03:36:58 -0800102 RTCMTLVideoView *realView = [[RTCMTLVideoView alloc] init];
denicijad2088152017-04-28 02:14:54 -0700103 self.frameMock = OCMClassMock([RTCVideoFrame class]);
104
Anders Carlsson75833902017-06-21 10:53:19 +0200105 [[self.frameMock reject] buffer];
denicijad2088152017-04-28 02:14:54 -0700106 [[self.classMock reject] createNV12Renderer];
107 [[self.classMock reject] createI420Renderer];
kthelgason954d9b92017-03-09 03:36:58 -0800108
109 // when
110 [realView renderFrame:nil];
kthelgason954d9b92017-03-09 03:36:58 -0800111 [realView drawInMTKView:self.metalViewMock];
112
113 // then
denicijad2088152017-04-28 02:14:54 -0700114 [self.frameMock verify];
115 [self.classMock verify];
116}
117
118- (void)testRTCVideoRenderFrameCallbackI420 {
119 // given
120 OCMStub([self.classMock isMetalAvailable]).andReturn(YES);
121 self.rendererI420Mock = [self rendererMockWithSuccessfulSetup:YES];
Anders Carlsson75833902017-06-21 10:53:19 +0200122 self.frameMock = [self frameMockWithCVPixelBuffer:NO];
denicijad2088152017-04-28 02:14:54 -0700123
124 OCMExpect([self.rendererI420Mock drawFrame:self.frameMock]);
125 OCMExpect([self.classMock createI420Renderer]).andReturn(self.rendererI420Mock);
126 [[self.classMock reject] createNV12Renderer];
127
128 RTCMTLVideoView *realView = [[RTCMTLVideoView alloc] init];
129
130 // when
131 [realView renderFrame:self.frameMock];
132 [realView drawInMTKView:self.metalViewMock];
133
134 // then
135 [self.rendererI420Mock verify];
136 [self.classMock verify];
137}
138
139- (void)testRTCVideoRenderFrameCallbackNV12 {
140 // given
141 OCMStub([self.classMock isMetalAvailable]).andReturn(YES);
142 self.rendererNV12Mock = [self rendererMockWithSuccessfulSetup:YES];
Anders Carlsson75833902017-06-21 10:53:19 +0200143 self.frameMock = [self frameMockWithCVPixelBuffer:YES];
denicijad2088152017-04-28 02:14:54 -0700144
145 OCMExpect([self.rendererNV12Mock drawFrame:self.frameMock]);
146 OCMExpect([self.classMock createNV12Renderer]).andReturn(self.rendererNV12Mock);
147 [[self.classMock reject] createI420Renderer];
148
149 RTCMTLVideoView *realView = [[RTCMTLVideoView alloc] init];
150
151 // when
152 [realView renderFrame:self.frameMock];
153 [realView drawInMTKView:self.metalViewMock];
154
155 // then
156 [self.rendererNV12Mock verify];
157 [self.classMock verify];
kthelgason954d9b92017-03-09 03:36:58 -0800158}
159@end
160
denicijad2088152017-04-28 02:14:54 -0700161TEST(RTCMTLVideoViewTests, InitAssertsIfMetalUnavailabe) {
kthelgason954d9b92017-03-09 03:36:58 -0800162 RTCMTLVideoViewTests *test = [[RTCMTLVideoViewTests alloc] init];
163 [test setup];
kthelgason954d9b92017-03-09 03:36:58 -0800164
denicijad2088152017-04-28 02:14:54 -0700165 [test testInitAssertsIfMetalUnavailabe];
kthelgason954d9b92017-03-09 03:36:58 -0800166 [test tearDown];
167}
168
169TEST(RTCMTLVideoViewTests, RTCVideoRenderNilFrameCallback) {
170 RTCMTLVideoViewTests *test = [[RTCMTLVideoViewTests alloc] init];
171 [test setup];
172 [test testRTCVideoRenderNilFrameCallback];
173 [test tearDown];
174}
175
denicijad2088152017-04-28 02:14:54 -0700176TEST(RTCMTLVideoViewTests, RTCVideoRenderFrameCallbackI420) {
kthelgason954d9b92017-03-09 03:36:58 -0800177 RTCMTLVideoViewTests *test = [[RTCMTLVideoViewTests alloc] init];
178 [test setup];
denicijad2088152017-04-28 02:14:54 -0700179
180 [test testRTCVideoRenderFrameCallbackI420];
181 [test tearDown];
182}
183
184TEST(RTCMTLVideoViewTests, RTCVideoRenderFrameCallbackNV12) {
185 RTCMTLVideoViewTests *test = [[RTCMTLVideoViewTests alloc] init];
186 [test setup];
187
188 [test testRTCVideoRenderFrameCallbackNV12];
kthelgason954d9b92017-03-09 03:36:58 -0800189 [test tearDown];
190}