1/* 2 * Copyright (c) 2013 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#if !defined(__has_feature) || !__has_feature(objc_arc) 12#error "This file requires ARC support." 13#endif 14 15#include "webrtc/modules/video_render/ios/video_render_ios_view.h" 16#include "webrtc/system_wrappers/include/trace.h" 17 18using namespace webrtc; 19 20@implementation VideoRenderIosView { 21 EAGLContext* _context; 22 rtc::scoped_ptr<webrtc::OpenGles20> _gles_renderer20; 23 int _frameBufferWidth; 24 int _frameBufferHeight; 25 unsigned int _defaultFrameBuffer; 26 unsigned int _colorRenderBuffer; 27} 28 29@synthesize context = context_; 30 31+ (Class)layerClass { 32 return [CAEAGLLayer class]; 33} 34 35- (id)initWithCoder:(NSCoder*)coder { 36 // init super class 37 self = [super initWithCoder:coder]; 38 if (self) { 39 _gles_renderer20.reset(new OpenGles20()); 40 } 41 return self; 42} 43 44- (id)init { 45 // init super class 46 self = [super init]; 47 if (self) { 48 _gles_renderer20.reset(new OpenGles20()); 49 } 50 return self; 51} 52 53- (id)initWithFrame:(CGRect)frame { 54 // init super class 55 self = [super initWithFrame:frame]; 56 if (self) { 57 _gles_renderer20.reset(new OpenGles20()); 58 } 59 return self; 60} 61 62- (void)dealloc { 63 if (_defaultFrameBuffer) { 64 glDeleteFramebuffers(1, &_defaultFrameBuffer); 65 _defaultFrameBuffer = 0; 66 } 67 68 if (_colorRenderBuffer) { 69 glDeleteRenderbuffers(1, &_colorRenderBuffer); 70 _colorRenderBuffer = 0; 71 } 72 73 [EAGLContext setCurrentContext:nil]; 74} 75 76- (NSString*)description { 77 return [NSString stringWithFormat: 78 @"A WebRTC implemented subclass of UIView." 79 "+Class method is overwritten, along with custom methods"]; 80} 81 82- (BOOL)createContext { 83 // create OpenGLES context from self layer class 84 CAEAGLLayer* eagl_layer = (CAEAGLLayer*)self.layer; 85 eagl_layer.opaque = YES; 86 eagl_layer.drawableProperties = 87 [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:NO], 88 kEAGLDrawablePropertyRetainedBacking, 89 kEAGLColorFormatRGBA8, 90 kEAGLDrawablePropertyColorFormat, 91 nil]; 92 _context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; 93 94 if (!_context) { 95 return NO; 96 } 97 98 if (![EAGLContext setCurrentContext:_context]) { 99 return NO; 100 } 101 102 // generates and binds the OpenGLES buffers 103 glGenFramebuffers(1, &_defaultFrameBuffer); 104 glBindFramebuffer(GL_FRAMEBUFFER, _defaultFrameBuffer); 105 106 // Create color render buffer and allocate backing store. 107 glGenRenderbuffers(1, &_colorRenderBuffer); 108 glBindRenderbuffer(GL_RENDERBUFFER, _colorRenderBuffer); 109 [_context renderbufferStorage:GL_RENDERBUFFER 110 fromDrawable:(CAEAGLLayer*)self.layer]; 111 glGetRenderbufferParameteriv( 112 GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &_frameBufferWidth); 113 glGetRenderbufferParameteriv( 114 GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &_frameBufferHeight); 115 glFramebufferRenderbuffer(GL_FRAMEBUFFER, 116 GL_COLOR_ATTACHMENT0, 117 GL_RENDERBUFFER, 118 _colorRenderBuffer); 119 120 if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { 121 return NO; 122 } 123 124 // set the frame buffer 125 glBindFramebuffer(GL_FRAMEBUFFER, _defaultFrameBuffer); 126 glViewport(0, 0, self.frame.size.width, self.frame.size.height); 127 128 return _gles_renderer20->Setup([self bounds].size.width, 129 [self bounds].size.height); 130} 131 132- (BOOL)presentFramebuffer { 133 if (![_context presentRenderbuffer:GL_RENDERBUFFER]) { 134 WEBRTC_TRACE(kTraceWarning, 135 kTraceVideoRenderer, 136 0, 137 "%s:%d [context present_renderbuffer] " 138 "returned false", 139 __FUNCTION__, 140 __LINE__); 141 } 142 return YES; 143} 144 145- (BOOL)renderFrame:(VideoFrame*)frameToRender { 146 if (![EAGLContext setCurrentContext:_context]) { 147 return NO; 148 } 149 150 return _gles_renderer20->Render(*frameToRender); 151} 152 153- (BOOL)setCoordinatesForZOrder:(const float)zOrder 154 Left:(const float)left 155 Top:(const float)top 156 Right:(const float)right 157 Bottom:(const float)bottom { 158 return _gles_renderer20->SetCoordinates(zOrder, left, top, right, bottom); 159} 160 161@end 162