Add checks that we don't redraw the previous frame.

Bug: webrtc:9149
Change-Id: Ia1f61fd43ea9be6c341a111595e8a290a809c72f
Reviewed-on: https://webrtc-review.googlesource.com/69810
Reviewed-by: Peter Hanspers <peterhanspers@webrtc.org>
Commit-Queue: Kári Helgason <kthelgason@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#22937}
This commit is contained in:
Kári Tristan Helgason 2018-04-16 11:39:53 +02:00 committed by Commit Bot
parent aedd090b72
commit 4f7b6406c4
2 changed files with 59 additions and 2 deletions

View File

@ -33,7 +33,9 @@
@property(atomic, strong) RTCVideoFrame *videoFrame;
@end
@implementation RTCMTLVideoView
@implementation RTCMTLVideoView {
int64_t _lastFrameTimeNs;
}
@synthesize rendererI420 = _rendererI420;
@synthesize rendererNV12 = _rendererNV12;
@ -106,7 +108,8 @@
- (void)drawInMTKView:(nonnull MTKView *)view {
NSAssert(view == self.metalView, @"Receiving draw callbacks from foreign instance.");
RTCVideoFrame *videoFrame = self.videoFrame;
if (!videoFrame) {
// Skip rendering if we've already rendered this frame.
if (!videoFrame || videoFrame.timeStampNs == _lastFrameTimeNs) {
return;
}
@ -116,6 +119,7 @@
if (![self.rendererNV12 addRenderingDestination:self.metalView]) {
self.rendererNV12 = nil;
RTCLogError(@"Failed to create NV12 renderer");
return;
}
}
[self.rendererNV12 drawFrame:videoFrame];
@ -125,10 +129,12 @@
if (![self.rendererI420 addRenderingDestination:self.metalView]) {
self.rendererI420 = nil;
RTCLogError(@"Failed to create I420 renderer");
return;
}
}
[self.rendererI420 drawFrame:videoFrame];
}
_lastFrameTimeNs = videoFrame.timeStampNs;
}
- (void)mtkView:(MTKView *)view drawableSizeWillChange:(CGSize)size {

View File

@ -73,6 +73,7 @@
} else {
OCMStub([frameMock buffer]).andReturn([[RTCI420Buffer alloc] initWithWidth:200 height:200]);
}
OCMStub([frameMock timeStampNs]).andReturn(arc4random_uniform(INT_MAX));
return frameMock;
}
@ -196,4 +197,54 @@
[self.classMock verify];
}
- (void)testDontRedrawOldFrame {
OCMStub([self.classMock isMetalAvailable]).andReturn(YES);
self.rendererNV12Mock = [self rendererMockWithSuccessfulSetup:YES];
self.frameMock = [self frameMockWithCVPixelBuffer:YES];
OCMExpect([self.rendererNV12Mock drawFrame:self.frameMock]);
OCMExpect([self.classMock createNV12Renderer]).andReturn(self.rendererNV12Mock);
[[self.classMock reject] createI420Renderer];
RTCMTLVideoView *realView = [[RTCMTLVideoView alloc] init];
[realView renderFrame:self.frameMock];
[realView drawInMTKView:nil];
[self.rendererNV12Mock verify];
[self.classMock verify];
[[self.rendererNV12Mock reject] drawFrame:[OCMArg any]];
[realView renderFrame:self.frameMock];
[realView drawInMTKView:nil];
[self.rendererNV12Mock verify];
}
- (void)testDoDrawNewFrame {
OCMStub([self.classMock isMetalAvailable]).andReturn(YES);
self.rendererNV12Mock = [self rendererMockWithSuccessfulSetup:YES];
self.frameMock = [self frameMockWithCVPixelBuffer:YES];
OCMExpect([self.rendererNV12Mock drawFrame:self.frameMock]);
OCMExpect([self.classMock createNV12Renderer]).andReturn(self.rendererNV12Mock);
[[self.classMock reject] createI420Renderer];
RTCMTLVideoView *realView = [[RTCMTLVideoView alloc] init];
[realView renderFrame:self.frameMock];
[realView drawInMTKView:nil];
[self.rendererNV12Mock verify];
[self.classMock verify];
// Get new frame.
self.frameMock = [self frameMockWithCVPixelBuffer:YES];
OCMExpect([self.rendererNV12Mock drawFrame:self.frameMock]);
[realView renderFrame:self.frameMock];
[realView drawInMTKView:nil];
[self.rendererNV12Mock verify];
}
@end