1935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org/*
2935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org * libjingle
3935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org * Copyright 2014, Google Inc.
4935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org *
5935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org * Redistribution and use in source and binary forms, with or without
6935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org * modification, are permitted provided that the following conditions are met:
7935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org *
8935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org *  1. Redistributions of source code must retain the above copyright notice,
9935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org *     this list of conditions and the following disclaimer.
10935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org *  2. Redistributions in binary form must reproduce the above copyright notice,
11935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org *     this list of conditions and the following disclaimer in the documentation
12935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org *     and/or other materials provided with the distribution.
13935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org *  3. The name of the author may not be used to endorse or promote products
14935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org *     derived from this software without specific prior written permission.
15935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org *
16935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org */
27935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org
28935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org#if !defined(__has_feature) || !__has_feature(objc_arc)
29935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org#error "This file requires ARC support."
30935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org#endif
31935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org
32935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org#import "RTCEAGLVideoView+Internal.h"
33935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org
34935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org#import <GLKit/GLKit.h>
35935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org
3652348f6729702ec8888955b7aa5d6b47a4727e6atkchin@webrtc.org#import "RTCOpenGLVideoRenderer.h"
37935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org#import "RTCVideoRenderer.h"
38935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org#import "RTCVideoTrack.h"
39935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org
405eb79e17e8d4d6df3791c863e5266ea906a7a37btkchin@webrtc.org// RTCDisplayLinkTimer wraps a CADisplayLink and is set to fire every two screen
415eb79e17e8d4d6df3791c863e5266ea906a7a37btkchin@webrtc.org// refreshes, which should be 30fps. We wrap the display link in order to avoid
425eb79e17e8d4d6df3791c863e5266ea906a7a37btkchin@webrtc.org// a retain cycle since CADisplayLink takes a strong reference onto its target.
435eb79e17e8d4d6df3791c863e5266ea906a7a37btkchin@webrtc.org// The timer is paused by default.
445eb79e17e8d4d6df3791c863e5266ea906a7a37btkchin@webrtc.org@interface RTCDisplayLinkTimer : NSObject
455eb79e17e8d4d6df3791c863e5266ea906a7a37btkchin@webrtc.org
465eb79e17e8d4d6df3791c863e5266ea906a7a37btkchin@webrtc.org@property(nonatomic) BOOL isPaused;
475eb79e17e8d4d6df3791c863e5266ea906a7a37btkchin@webrtc.org
485eb79e17e8d4d6df3791c863e5266ea906a7a37btkchin@webrtc.org- (instancetype)initWithTimerHandler:(void (^)(void))timerHandler;
495eb79e17e8d4d6df3791c863e5266ea906a7a37btkchin@webrtc.org- (void)invalidate;
505eb79e17e8d4d6df3791c863e5266ea906a7a37btkchin@webrtc.org
515eb79e17e8d4d6df3791c863e5266ea906a7a37btkchin@webrtc.org@end
525eb79e17e8d4d6df3791c863e5266ea906a7a37btkchin@webrtc.org
535eb79e17e8d4d6df3791c863e5266ea906a7a37btkchin@webrtc.org@implementation RTCDisplayLinkTimer {
545eb79e17e8d4d6df3791c863e5266ea906a7a37btkchin@webrtc.org  CADisplayLink* _displayLink;
555eb79e17e8d4d6df3791c863e5266ea906a7a37btkchin@webrtc.org  void (^_timerHandler)(void);
565eb79e17e8d4d6df3791c863e5266ea906a7a37btkchin@webrtc.org}
575eb79e17e8d4d6df3791c863e5266ea906a7a37btkchin@webrtc.org
585eb79e17e8d4d6df3791c863e5266ea906a7a37btkchin@webrtc.org- (instancetype)initWithTimerHandler:(void (^)(void))timerHandler {
595eb79e17e8d4d6df3791c863e5266ea906a7a37btkchin@webrtc.org  NSParameterAssert(timerHandler);
605eb79e17e8d4d6df3791c863e5266ea906a7a37btkchin@webrtc.org  if (self = [super init]) {
615eb79e17e8d4d6df3791c863e5266ea906a7a37btkchin@webrtc.org    _timerHandler = timerHandler;
625eb79e17e8d4d6df3791c863e5266ea906a7a37btkchin@webrtc.org    _displayLink =
635eb79e17e8d4d6df3791c863e5266ea906a7a37btkchin@webrtc.org        [CADisplayLink displayLinkWithTarget:self
645eb79e17e8d4d6df3791c863e5266ea906a7a37btkchin@webrtc.org                                    selector:@selector(displayLinkDidFire:)];
655eb79e17e8d4d6df3791c863e5266ea906a7a37btkchin@webrtc.org    _displayLink.paused = YES;
665eb79e17e8d4d6df3791c863e5266ea906a7a37btkchin@webrtc.org    // Set to half of screen refresh, which should be 30fps.
675eb79e17e8d4d6df3791c863e5266ea906a7a37btkchin@webrtc.org    [_displayLink setFrameInterval:2];
685eb79e17e8d4d6df3791c863e5266ea906a7a37btkchin@webrtc.org    [_displayLink addToRunLoop:[NSRunLoop currentRunLoop]
695eb79e17e8d4d6df3791c863e5266ea906a7a37btkchin@webrtc.org                       forMode:NSRunLoopCommonModes];
705eb79e17e8d4d6df3791c863e5266ea906a7a37btkchin@webrtc.org  }
715eb79e17e8d4d6df3791c863e5266ea906a7a37btkchin@webrtc.org  return self;
725eb79e17e8d4d6df3791c863e5266ea906a7a37btkchin@webrtc.org}
735eb79e17e8d4d6df3791c863e5266ea906a7a37btkchin@webrtc.org
745eb79e17e8d4d6df3791c863e5266ea906a7a37btkchin@webrtc.org- (void)dealloc {
755eb79e17e8d4d6df3791c863e5266ea906a7a37btkchin@webrtc.org  [self invalidate];
765eb79e17e8d4d6df3791c863e5266ea906a7a37btkchin@webrtc.org}
775eb79e17e8d4d6df3791c863e5266ea906a7a37btkchin@webrtc.org
785eb79e17e8d4d6df3791c863e5266ea906a7a37btkchin@webrtc.org- (BOOL)isPaused {
795eb79e17e8d4d6df3791c863e5266ea906a7a37btkchin@webrtc.org  return _displayLink.paused;
805eb79e17e8d4d6df3791c863e5266ea906a7a37btkchin@webrtc.org}
815eb79e17e8d4d6df3791c863e5266ea906a7a37btkchin@webrtc.org
825eb79e17e8d4d6df3791c863e5266ea906a7a37btkchin@webrtc.org- (void)setIsPaused:(BOOL)isPaused {
835eb79e17e8d4d6df3791c863e5266ea906a7a37btkchin@webrtc.org  _displayLink.paused = isPaused;
845eb79e17e8d4d6df3791c863e5266ea906a7a37btkchin@webrtc.org}
855eb79e17e8d4d6df3791c863e5266ea906a7a37btkchin@webrtc.org
865eb79e17e8d4d6df3791c863e5266ea906a7a37btkchin@webrtc.org- (void)invalidate {
875eb79e17e8d4d6df3791c863e5266ea906a7a37btkchin@webrtc.org  [_displayLink invalidate];
885eb79e17e8d4d6df3791c863e5266ea906a7a37btkchin@webrtc.org}
895eb79e17e8d4d6df3791c863e5266ea906a7a37btkchin@webrtc.org
905eb79e17e8d4d6df3791c863e5266ea906a7a37btkchin@webrtc.org- (void)displayLinkDidFire:(CADisplayLink*)displayLink {
915eb79e17e8d4d6df3791c863e5266ea906a7a37btkchin@webrtc.org  _timerHandler();
925eb79e17e8d4d6df3791c863e5266ea906a7a37btkchin@webrtc.org}
935eb79e17e8d4d6df3791c863e5266ea906a7a37btkchin@webrtc.org
945eb79e17e8d4d6df3791c863e5266ea906a7a37btkchin@webrtc.org@end
955eb79e17e8d4d6df3791c863e5266ea906a7a37btkchin@webrtc.org
96935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org@interface RTCEAGLVideoView () <GLKViewDelegate>
9752348f6729702ec8888955b7aa5d6b47a4727e6atkchin@webrtc.org// |i420Frame| is set when we receive a frame from a worker thread and is read
9852348f6729702ec8888955b7aa5d6b47a4727e6atkchin@webrtc.org// from the display link callback so atomicity is required.
99935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org@property(atomic, strong) RTCI420Frame* i420Frame;
1005eb79e17e8d4d6df3791c863e5266ea906a7a37btkchin@webrtc.org@property(nonatomic, readonly) GLKView* glkView;
1015eb79e17e8d4d6df3791c863e5266ea906a7a37btkchin@webrtc.org@property(nonatomic, readonly) RTCOpenGLVideoRenderer* glRenderer;
102935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org@end
103935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org
104935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org@implementation RTCEAGLVideoView {
1055eb79e17e8d4d6df3791c863e5266ea906a7a37btkchin@webrtc.org  RTCDisplayLinkTimer* _timer;
106935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org  GLKView* _glkView;
10752348f6729702ec8888955b7aa5d6b47a4727e6atkchin@webrtc.org  RTCOpenGLVideoRenderer* _glRenderer;
108935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org  RTCVideoRenderer* _videoRenderer;
109935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org}
110935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org
111935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org- (instancetype)initWithFrame:(CGRect)frame {
112935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org  if (self = [super initWithFrame:frame]) {
113935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org    EAGLContext* glContext =
114935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org        [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
11552348f6729702ec8888955b7aa5d6b47a4727e6atkchin@webrtc.org    _glRenderer = [[RTCOpenGLVideoRenderer alloc] initWithContext:glContext];
116935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org
117935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org    // GLKView manages a framebuffer for us.
118935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org    _glkView = [[GLKView alloc] initWithFrame:CGRectZero
119935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org                                      context:glContext];
120935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org    _glkView.drawableColorFormat = GLKViewDrawableColorFormatRGBA8888;
121935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org    _glkView.drawableDepthFormat = GLKViewDrawableDepthFormatNone;
122935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org    _glkView.drawableStencilFormat = GLKViewDrawableStencilFormatNone;
123935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org    _glkView.drawableMultisample = GLKViewDrawableMultisampleNone;
124935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org    _glkView.delegate = self;
125935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org    _glkView.layer.masksToBounds = YES;
126935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org    [self addSubview:_glkView];
127935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org
128935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org    // Listen to application state in order to clean up OpenGL before app goes
129935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org    // away.
130935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org    NSNotificationCenter* notificationCenter =
131935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org        [NSNotificationCenter defaultCenter];
132935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org    [notificationCenter addObserver:self
133935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org                           selector:@selector(willResignActive)
134935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org                               name:UIApplicationWillResignActiveNotification
135935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org                             object:nil];
136935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org    [notificationCenter addObserver:self
137935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org                           selector:@selector(didBecomeActive)
138935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org                               name:UIApplicationDidBecomeActiveNotification
139935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org                             object:nil];
1405eb79e17e8d4d6df3791c863e5266ea906a7a37btkchin@webrtc.org
1415eb79e17e8d4d6df3791c863e5266ea906a7a37btkchin@webrtc.org    // Frames are received on a separate thread, so we poll for current frame
1425eb79e17e8d4d6df3791c863e5266ea906a7a37btkchin@webrtc.org    // using a refresh rate proportional to screen refresh frequency. This
1435eb79e17e8d4d6df3791c863e5266ea906a7a37btkchin@webrtc.org    // occurs on the main thread.
1445eb79e17e8d4d6df3791c863e5266ea906a7a37btkchin@webrtc.org    __weak RTCEAGLVideoView* weakSelf = self;
1455eb79e17e8d4d6df3791c863e5266ea906a7a37btkchin@webrtc.org    _timer = [[RTCDisplayLinkTimer alloc] initWithTimerHandler:^{
1465eb79e17e8d4d6df3791c863e5266ea906a7a37btkchin@webrtc.org      RTCEAGLVideoView* strongSelf = weakSelf;
1475eb79e17e8d4d6df3791c863e5266ea906a7a37btkchin@webrtc.org      // Don't render if frame hasn't changed.
1485eb79e17e8d4d6df3791c863e5266ea906a7a37btkchin@webrtc.org      if (strongSelf.glRenderer.lastDrawnFrame == strongSelf.i420Frame) {
1495eb79e17e8d4d6df3791c863e5266ea906a7a37btkchin@webrtc.org        return;
1505eb79e17e8d4d6df3791c863e5266ea906a7a37btkchin@webrtc.org      }
1515eb79e17e8d4d6df3791c863e5266ea906a7a37btkchin@webrtc.org      // This tells the GLKView that it's dirty, which will then call the
1525eb79e17e8d4d6df3791c863e5266ea906a7a37btkchin@webrtc.org      // GLKViewDelegate method implemented below.
1535eb79e17e8d4d6df3791c863e5266ea906a7a37btkchin@webrtc.org      [strongSelf.glkView setNeedsDisplay];
1545eb79e17e8d4d6df3791c863e5266ea906a7a37btkchin@webrtc.org    }];
155935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org    _videoRenderer = [[RTCVideoRenderer alloc] initWithDelegate:self];
156935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org    [self setupGL];
157935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org  }
158935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org  return self;
159935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org}
160935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org
161935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org- (void)dealloc {
162935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org  [[NSNotificationCenter defaultCenter] removeObserver:self];
163935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org  UIApplicationState appState =
164935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org      [UIApplication sharedApplication].applicationState;
165935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org  if (appState == UIApplicationStateActive) {
166935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org    [self teardownGL];
167935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org  }
1685eb79e17e8d4d6df3791c863e5266ea906a7a37btkchin@webrtc.org  [_timer invalidate];
169935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org}
170935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org
171935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org- (void)setVideoTrack:(RTCVideoTrack*)videoTrack {
172935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org  if (_videoTrack == videoTrack) {
173935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org    return;
174935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org  }
175935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org  [_videoTrack removeRenderer:_videoRenderer];
176fdfa16850f56fffaf3bfd26ed132bdec1fa99d32tkchin@webrtc.org  self.i420Frame = nil;
177935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org  _videoTrack = videoTrack;
178935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org  [_videoTrack addRenderer:_videoRenderer];
179935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org  // TODO(tkchin): potentially handle changes in track state - e.g. render
180935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org  // black if track fails.
181935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org}
182935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org
183935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org#pragma mark - UIView
184935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org
185935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org- (void)layoutSubviews {
186935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org  [super layoutSubviews];
187935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org  _glkView.frame = self.bounds;
188935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org}
189935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org
190935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org#pragma mark - GLKViewDelegate
191935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org
192935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org// This method is called when the GLKView's content is dirty and needs to be
193935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org// redrawn. This occurs on main thread.
194935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org- (void)glkView:(GLKView*)view drawInRect:(CGRect)rect {
195fdfa16850f56fffaf3bfd26ed132bdec1fa99d32tkchin@webrtc.org  // The renderer will draw the frame to the framebuffer corresponding to the
196fdfa16850f56fffaf3bfd26ed132bdec1fa99d32tkchin@webrtc.org  // one used by |view|.
197fdfa16850f56fffaf3bfd26ed132bdec1fa99d32tkchin@webrtc.org  [_glRenderer drawFrame:self.i420Frame];
198935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org}
199935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org
200935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org#pragma mark - Private
201935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org
202935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org- (void)setupGL {
203935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org  [_glRenderer setupGL];
2045eb79e17e8d4d6df3791c863e5266ea906a7a37btkchin@webrtc.org  _timer.isPaused = NO;
205935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org}
206935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org
207935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org- (void)teardownGL {
2085eb79e17e8d4d6df3791c863e5266ea906a7a37btkchin@webrtc.org  _timer.isPaused = YES;
209935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org  [_glkView deleteDrawable];
210935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org  [_glRenderer teardownGL];
211935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org}
212935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org
213935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org- (void)didBecomeActive {
214935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org  [self setupGL];
215935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org}
216935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org
217935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org- (void)willResignActive {
218935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org  [self teardownGL];
219935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org}
220935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org
221935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org@end
222935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org
223935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org@implementation RTCEAGLVideoView (Internal)
224935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org
225935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org#pragma mark - RTCVideoRendererDelegate
226935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org
227935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org// These methods are called when the video track has frame information to
228935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org// provide. This occurs on non-main thread.
229935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org- (void)renderer:(RTCVideoRenderer*)renderer
230935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org      didSetSize:(CGSize)size {
2315eb79e17e8d4d6df3791c863e5266ea906a7a37btkchin@webrtc.org  __weak RTCEAGLVideoView* weakSelf = self;
23252348f6729702ec8888955b7aa5d6b47a4727e6atkchin@webrtc.org  dispatch_async(dispatch_get_main_queue(), ^{
2335eb79e17e8d4d6df3791c863e5266ea906a7a37btkchin@webrtc.org    RTCEAGLVideoView* strongSelf = weakSelf;
2345eb79e17e8d4d6df3791c863e5266ea906a7a37btkchin@webrtc.org    [strongSelf.delegate videoView:strongSelf didChangeVideoSize:size];
23552348f6729702ec8888955b7aa5d6b47a4727e6atkchin@webrtc.org  });
236935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org}
237935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org
238935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org- (void)renderer:(RTCVideoRenderer*)renderer
239935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org    didReceiveFrame:(RTCI420Frame*)frame {
240935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org  self.i420Frame = frame;
241935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org}
242935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org
243935b8f2c093115e48d105962c5f403a5c8e76f7etkchin@webrtc.org@end
244