OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2017 The WebRTC project authors. All Rights Reserved. | 2 * Copyright 2017 The WebRTC project authors. All Rights Reserved. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license | 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 | 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 | 6 * tree. An additional intellectual property rights grant can be found |
7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
9 */ | 9 */ |
10 | 10 |
11 #import <Foundation/Foundation.h> | 11 #import <Foundation/Foundation.h> |
12 #import <OCMock/OCMock.h> | 12 #import <OCMock/OCMock.h> |
13 | 13 |
14 #include "webrtc/base/gunit.h" | 14 #include "webrtc/base/gunit.h" |
15 | 15 |
16 #include <Metal/RTCMTLNV12Renderer.h> | 16 #include <Metal/RTCMTLNV12Renderer.h> |
17 #include <WebRTC/RTCMTLVideoView.h> | 17 #include <WebRTC/RTCMTLVideoView.h> |
18 | 18 |
19 // Extension of RTCMTLVideoView for testing purposes. | 19 // Extension of RTCMTLVideoView for testing purposes. |
20 @interface RTCMTLVideoView (Testing) | 20 @interface RTCMTLVideoView (Testing) |
21 @property(nonatomic, strong) id<RTCMTLRenderer> renderer; | 21 @property(nonatomic, strong) id<RTCMTLRenderer> rendererI420; |
| 22 @property(nonatomic, strong) id<RTCMTLRenderer> rendererNV12; |
22 @property(nonatomic, strong) UIView* metalView; | 23 @property(nonatomic, strong) UIView* metalView; |
23 @property(atomic, strong) RTCVideoFrame* videoFrame; | 24 @property(atomic, strong) RTCVideoFrame* videoFrame; |
24 | 25 |
25 + (BOOL)isMetalAvailable; | 26 + (BOOL)isMetalAvailable; |
26 + (UIView*)createMetalView:(CGRect)frame; | 27 + (UIView*)createMetalView:(CGRect)frame; |
27 + (id<RTCMTLRenderer>)createMetalRenderer; | 28 + (id<RTCMTLRenderer>)createNV12Renderer; |
| 29 + (id<RTCMTLRenderer>)createI420Renderer; |
28 - (void)drawInMTKView:(id)view; | 30 - (void)drawInMTKView:(id)view; |
29 @end | 31 @end |
30 | 32 |
31 @interface RTCMTLVideoViewTests : NSObject | 33 @interface RTCMTLVideoViewTests : NSObject |
32 @property(nonatomic, strong) id classMock; | 34 @property(nonatomic, strong) id classMock; |
33 @property(nonatomic, strong) id metalViewMock; | 35 @property(nonatomic, strong) id metalViewMock; |
34 @property(nonatomic, strong) id rendererMock; | 36 @property(nonatomic, strong) id rendererNV12Mock; |
| 37 @property(nonatomic, strong) id rendererI420Mock; |
35 @end | 38 @end |
36 | 39 |
37 @implementation RTCMTLVideoViewTests | 40 @implementation RTCMTLVideoViewTests |
38 | 41 |
39 @synthesize classMock = _classMock; | 42 @synthesize classMock = _classMock; |
40 @synthesize metalViewMock = _metalViewMock; | 43 @synthesize metalViewMock = _metalViewMock; |
41 @synthesize rendererMock = _rendererMock; | 44 @synthesize rendererNV12Mock = _rendererNV12Mock; |
| 45 @synthesize rendererI420Mock = _rendererI420Mock; |
42 | 46 |
43 - (void)setup { | 47 - (void)setup { |
44 self.classMock = OCMClassMock([RTCMTLVideoView class]); | 48 self.classMock = OCMClassMock([RTCMTLVideoView class]); |
45 | 49 |
46 self.metalViewMock = OCMClassMock([RTCMTLVideoViewTests class]); | 50 self.metalViewMock = OCMClassMock([RTCMTLVideoViewTests class]); |
47 // NOTE: OCMock doesen't provide modern syntax for -ignoringNonObjectArgs. | 51 // NOTE: OCMock doesen't provide modern syntax for -ignoringNonObjectArgs. |
48 [[[[self.classMock stub] ignoringNonObjectArgs] andReturn:self.metalViewMock] | 52 [[[[self.classMock stub] ignoringNonObjectArgs] andReturn:self.metalViewMock] |
49 createMetalView:CGRectZero]; | 53 createMetalView:CGRectZero]; |
50 | 54 |
51 self.rendererMock = OCMProtocolMock(@protocol(RTCMTLRenderer)); | 55 self.rendererNV12Mock = OCMProtocolMock(@protocol(RTCMTLRenderer)); |
52 OCMStub([self.classMock createMetalRenderer]).andReturn(self.rendererMock); | 56 OCMStub([self.classMock createI420Renderer]).andReturn(self.rendererI420Mock); |
| 57 self.rendererI420Mock = OCMProtocolMock(@protocol(RTCMTLRenderer)); |
| 58 OCMStub([self.classMock createNV12Renderer]).andReturn(self.rendererNV12Mock); |
53 } | 59 } |
54 | 60 |
55 - (void)tearDown { | 61 - (void)tearDown { |
56 [self.classMock stopMocking]; | 62 [self.classMock stopMocking]; |
57 [self.rendererMock stopMocking]; | 63 [self.rendererI420Mock stopMocking]; |
| 64 [self.rendererNV12Mock stopMocking]; |
58 [self.metalViewMock stopMocking]; | 65 [self.metalViewMock stopMocking]; |
59 self.classMock = nil; | 66 self.classMock = nil; |
60 self.rendererMock = nil; | 67 self.rendererI420Mock = nil; |
| 68 self.rendererNV12Mock = nil; |
61 self.metalViewMock = nil; | 69 self.metalViewMock = nil; |
62 } | 70 } |
63 | 71 |
64 - (void)testMetalConfigureNotExecuted { | 72 - (void)testMetalConfigureNotExecuted { |
65 // when | 73 // when |
66 OCMStub([self.classMock isMetalAvailable]).andReturn(NO); | 74 OCMStub([self.classMock isMetalAvailable]).andReturn(NO); |
67 RTCMTLVideoView *realView = [[RTCMTLVideoView alloc] init]; | 75 RTCMTLVideoView *realView = [[RTCMTLVideoView alloc] init]; |
68 | 76 |
69 // then | 77 // then |
70 EXPECT_TRUE(realView.renderer == nil); | 78 EXPECT_EQ(realView.rendererI420, nil); |
71 EXPECT_TRUE(realView.metalView == nil); | 79 EXPECT_EQ(realView.rendererNV12, nil); |
| 80 EXPECT_EQ(realView.metalView, nil); |
72 } | 81 } |
73 | 82 |
74 - (void)testMetalConfigureExecuted { | 83 - (void)testMetalConfigureExecuted { |
75 // given | 84 // given |
76 OCMStub([self.classMock isMetalAvailable]).andReturn(YES); | 85 OCMStub([self.classMock isMetalAvailable]).andReturn(YES); |
77 OCMStub([self.rendererMock addRenderingDestination:self.metalViewMock]) | 86 OCMStub([self.rendererNV12Mock addRenderingDestination:self.metalViewMock]).an
dReturn(NO); |
78 .andReturn(NO); | 87 OCMStub([self.rendererI420Mock addRenderingDestination:self.metalViewMock]).an
dReturn(NO); |
79 | 88 |
80 // when | 89 // when |
81 RTCMTLVideoView *realView = [[RTCMTLVideoView alloc] init]; | 90 RTCMTLVideoView *realView = [[RTCMTLVideoView alloc] init]; |
82 | 91 |
83 // then | 92 // then |
84 EXPECT_TRUE(realView.renderer == nil); | 93 EXPECT_EQ(realView.rendererI420, nil); |
| 94 EXPECT_EQ(realView.rendererNV12, nil); |
85 EXPECT_TRUE(realView.metalView != nil); | 95 EXPECT_TRUE(realView.metalView != nil); |
86 } | 96 } |
87 | 97 |
88 - (void)testMetalDrawCallback { | |
89 // given | |
90 OCMStub([self.classMock isMetalAvailable]).andReturn(NO); | |
91 OCMExpect([self.rendererMock drawFrame:[OCMArg any]]); | |
92 RTCMTLVideoView *realView = [[RTCMTLVideoView alloc] init]; | |
93 realView.metalView = self.metalViewMock; | |
94 realView.renderer = self.rendererMock; | |
95 | |
96 // when | |
97 [realView drawInMTKView:self.metalViewMock]; | |
98 | |
99 // then | |
100 [self.rendererMock verify]; | |
101 } | |
102 | |
103 - (void)testRTCVideoRenderNilFrameCallback { | 98 - (void)testRTCVideoRenderNilFrameCallback { |
104 // given | 99 // given |
105 OCMStub([self.classMock isMetalAvailable]).andReturn(NO); | |
106 RTCMTLVideoView *realView = [[RTCMTLVideoView alloc] init]; | 100 RTCMTLVideoView *realView = [[RTCMTLVideoView alloc] init]; |
107 | 101 |
108 // when | 102 // when |
109 [realView renderFrame:nil]; | 103 [realView renderFrame:nil]; |
110 | 104 |
111 // then | 105 // then |
112 EXPECT_TRUE(realView.videoFrame == nil); | 106 EXPECT_TRUE(realView.videoFrame == nil); |
113 } | 107 } |
114 | 108 |
115 - (void)testRTCVideoRenderFrameCallback { | 109 - (void)testRTCVideoRenderFrameCallbackI420 { |
116 // given | 110 // given |
117 OCMStub([self.classMock isMetalAvailable]).andReturn(NO); | |
118 RTCMTLVideoView *realView = [[RTCMTLVideoView alloc] init]; | 111 RTCMTLVideoView *realView = [[RTCMTLVideoView alloc] init]; |
119 id frame = OCMClassMock([RTCVideoFrame class]); | 112 id frame = OCMClassMock([RTCVideoFrame class]); |
| 113 |
120 realView.metalView = self.metalViewMock; | 114 realView.metalView = self.metalViewMock; |
121 realView.renderer = self.rendererMock; | 115 realView.rendererI420 = self.rendererI420Mock; |
122 OCMExpect([self.rendererMock drawFrame:frame]); | 116 OCMExpect([self.rendererI420Mock drawFrame:frame]); |
123 | 117 |
124 // when | 118 // when |
125 [realView renderFrame:frame]; | 119 [realView renderFrame:frame]; |
| 120 [realView drawInMTKView:self.metalViewMock]; |
| 121 |
| 122 // then |
| 123 EXPECT_EQ(realView.videoFrame, frame); |
| 124 [self.rendererI420Mock verify]; |
| 125 } |
| 126 |
| 127 - (void)testRTCVideoRenderFrameCallbackNV12 { |
| 128 // given |
| 129 RTCMTLVideoView *realView = [[RTCMTLVideoView alloc] init]; |
| 130 id frame = OCMClassMock([RTCVideoFrame class]); |
| 131 OCMStub([frame nativeHandle]).andReturn((CVPixelBufferRef)[OCMArg anyPointer])
; |
| 132 |
| 133 realView.metalView = self.metalViewMock; |
| 134 realView.rendererNV12 = self.rendererNV12Mock; |
| 135 OCMExpect([self.rendererNV12Mock drawFrame:frame]); |
| 136 |
| 137 // when |
| 138 [realView renderFrame:frame]; |
126 [realView drawInMTKView:self.metalViewMock]; | 139 [realView drawInMTKView:self.metalViewMock]; |
127 | 140 |
128 // then | 141 // then |
129 EXPECT_EQ(realView.videoFrame, frame); | 142 EXPECT_EQ(realView.videoFrame, frame); |
130 [self.rendererMock verify]; | 143 [self.rendererNV12Mock verify]; |
131 } | 144 } |
132 @end | 145 @end |
133 | 146 |
134 TEST(RTCMTLVideoViewTests, MetalConfigureNotExecuted) { | 147 TEST(RTCMTLVideoViewTests, MetalConfigureNotExecuted) { |
135 RTCMTLVideoViewTests *test = [[RTCMTLVideoViewTests alloc] init]; | 148 RTCMTLVideoViewTests *test = [[RTCMTLVideoViewTests alloc] init]; |
136 [test setup]; | 149 [test setup]; |
137 [test testMetalConfigureNotExecuted]; | 150 [test testMetalConfigureNotExecuted]; |
138 [test tearDown]; | 151 [test tearDown]; |
139 } | 152 } |
140 | 153 |
141 | 154 |
142 TEST(RTCMTLVideoViewTests, MetalConfigureExecuted) { | 155 TEST(RTCMTLVideoViewTests, MetalConfigureExecuted) { |
143 RTCMTLVideoViewTests *test = [[RTCMTLVideoViewTests alloc] init]; | 156 RTCMTLVideoViewTests *test = [[RTCMTLVideoViewTests alloc] init]; |
144 [test setup]; | 157 [test setup]; |
145 [test testMetalConfigureExecuted]; | 158 [test testMetalConfigureExecuted]; |
146 [test tearDown]; | 159 [test tearDown]; |
147 } | 160 } |
148 | 161 |
149 TEST(RTCMTLVideoViewTests, MetalDrawCallback) { | |
150 RTCMTLVideoViewTests *test = [[RTCMTLVideoViewTests alloc] init]; | |
151 [test setup]; | |
152 [test testMetalDrawCallback]; | |
153 [test tearDown]; | |
154 } | |
155 | |
156 TEST(RTCMTLVideoViewTests, RTCVideoRenderNilFrameCallback) { | 162 TEST(RTCMTLVideoViewTests, RTCVideoRenderNilFrameCallback) { |
157 RTCMTLVideoViewTests *test = [[RTCMTLVideoViewTests alloc] init]; | 163 RTCMTLVideoViewTests *test = [[RTCMTLVideoViewTests alloc] init]; |
158 [test setup]; | 164 [test setup]; |
159 [test testRTCVideoRenderNilFrameCallback]; | 165 [test testRTCVideoRenderNilFrameCallback]; |
160 [test tearDown]; | 166 [test tearDown]; |
161 } | 167 } |
162 | 168 |
163 TEST(RTCMTLVideoViewTests, RTCVideoRenderFrameCallback) { | 169 TEST(RTCMTLVideoViewTests, RTCVideoRenderFrameCallbackI420) { |
164 RTCMTLVideoViewTests *test = [[RTCMTLVideoViewTests alloc] init]; | 170 RTCMTLVideoViewTests *test = [[RTCMTLVideoViewTests alloc] init]; |
165 [test setup]; | 171 [test setup]; |
166 [test testRTCVideoRenderFrameCallback]; | 172 [test testRTCVideoRenderFrameCallbackI420]; |
167 [test tearDown]; | 173 [test tearDown]; |
168 } | 174 } |
| 175 |
| 176 TEST(RTCMTLVideoViewTests, RTCVideoRenderFrameCallbackNV12) { |
| 177 RTCMTLVideoViewTests *test = [[RTCMTLVideoViewTests alloc] init]; |
| 178 [test setup]; |
| 179 [test testRTCVideoRenderFrameCallbackNV12]; |
| 180 [test tearDown]; |
| 181 } |
OLD | NEW |