Index: webrtc/modules/video_render/ios/video_render_ios_view.mm |
diff --git a/webrtc/modules/video_render/ios/video_render_ios_view.mm b/webrtc/modules/video_render/ios/video_render_ios_view.mm |
new file mode 100644 |
index 0000000000000000000000000000000000000000..b106ffa5c4f925a8f59999394e8b5e1b4fd68107 |
--- /dev/null |
+++ b/webrtc/modules/video_render/ios/video_render_ios_view.mm |
@@ -0,0 +1,163 @@ |
+/* |
+ * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. |
+ * |
+ * Use of this source code is governed by a BSD-style license |
+ * that can be found in the LICENSE file in the root of the source |
+ * tree. An additional intellectual property rights grant can be found |
+ * in the file PATENTS. All contributing project authors may |
+ * be found in the AUTHORS file in the root of the source tree. |
+ */ |
+ |
+#if !defined(__has_feature) || !__has_feature(objc_arc) |
+#error "This file requires ARC support." |
+#endif |
+ |
+#include <memory> |
+ |
+#include "webrtc/modules/video_render/ios/video_render_ios_view.h" |
+#include "webrtc/system_wrappers/include/trace.h" |
+ |
+using namespace webrtc; |
+ |
+@implementation VideoRenderIosView { |
+ EAGLContext* _context; |
+ std::unique_ptr<webrtc::OpenGles20> _gles_renderer20; |
+ int _frameBufferWidth; |
+ int _frameBufferHeight; |
+ unsigned int _defaultFrameBuffer; |
+ unsigned int _colorRenderBuffer; |
+} |
+ |
+@synthesize context = context_; |
+ |
++ (Class)layerClass { |
+ return [CAEAGLLayer class]; |
+} |
+ |
+- (id)initWithCoder:(NSCoder*)coder { |
+ // init super class |
+ self = [super initWithCoder:coder]; |
+ if (self) { |
+ _gles_renderer20.reset(new OpenGles20()); |
+ } |
+ return self; |
+} |
+ |
+- (id)init { |
+ // init super class |
+ self = [super init]; |
+ if (self) { |
+ _gles_renderer20.reset(new OpenGles20()); |
+ } |
+ return self; |
+} |
+ |
+- (id)initWithFrame:(CGRect)frame { |
+ // init super class |
+ self = [super initWithFrame:frame]; |
+ if (self) { |
+ _gles_renderer20.reset(new OpenGles20()); |
+ } |
+ return self; |
+} |
+ |
+- (void)dealloc { |
+ if (_defaultFrameBuffer) { |
+ glDeleteFramebuffers(1, &_defaultFrameBuffer); |
+ _defaultFrameBuffer = 0; |
+ } |
+ |
+ if (_colorRenderBuffer) { |
+ glDeleteRenderbuffers(1, &_colorRenderBuffer); |
+ _colorRenderBuffer = 0; |
+ } |
+ |
+ [EAGLContext setCurrentContext:nil]; |
+} |
+ |
+- (NSString*)description { |
+ return [NSString stringWithFormat: |
+ @"A WebRTC implemented subclass of UIView." |
+ "+Class method is overwritten, along with custom methods"]; |
+} |
+ |
+- (BOOL)createContext { |
+ // create OpenGLES context from self layer class |
+ CAEAGLLayer* eagl_layer = (CAEAGLLayer*)self.layer; |
+ eagl_layer.opaque = YES; |
+ eagl_layer.drawableProperties = |
+ [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:NO], |
+ kEAGLDrawablePropertyRetainedBacking, |
+ kEAGLColorFormatRGBA8, |
+ kEAGLDrawablePropertyColorFormat, |
+ nil]; |
+ _context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; |
+ |
+ if (!_context) { |
+ return NO; |
+ } |
+ |
+ if (![EAGLContext setCurrentContext:_context]) { |
+ return NO; |
+ } |
+ |
+ // generates and binds the OpenGLES buffers |
+ glGenFramebuffers(1, &_defaultFrameBuffer); |
+ glBindFramebuffer(GL_FRAMEBUFFER, _defaultFrameBuffer); |
+ |
+ // Create color render buffer and allocate backing store. |
+ glGenRenderbuffers(1, &_colorRenderBuffer); |
+ glBindRenderbuffer(GL_RENDERBUFFER, _colorRenderBuffer); |
+ [_context renderbufferStorage:GL_RENDERBUFFER |
+ fromDrawable:(CAEAGLLayer*)self.layer]; |
+ glGetRenderbufferParameteriv( |
+ GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &_frameBufferWidth); |
+ glGetRenderbufferParameteriv( |
+ GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &_frameBufferHeight); |
+ glFramebufferRenderbuffer(GL_FRAMEBUFFER, |
+ GL_COLOR_ATTACHMENT0, |
+ GL_RENDERBUFFER, |
+ _colorRenderBuffer); |
+ |
+ if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { |
+ return NO; |
+ } |
+ |
+ // set the frame buffer |
+ glBindFramebuffer(GL_FRAMEBUFFER, _defaultFrameBuffer); |
+ glViewport(0, 0, self.frame.size.width, self.frame.size.height); |
+ |
+ return _gles_renderer20->Setup([self bounds].size.width, |
+ [self bounds].size.height); |
+} |
+ |
+- (BOOL)presentFramebuffer { |
+ if (![_context presentRenderbuffer:GL_RENDERBUFFER]) { |
+ WEBRTC_TRACE(kTraceWarning, |
+ kTraceVideoRenderer, |
+ 0, |
+ "%s:%d [context present_renderbuffer] " |
+ "returned false", |
+ __FUNCTION__, |
+ __LINE__); |
+ } |
+ return YES; |
+} |
+ |
+- (BOOL)renderFrame:(VideoFrame*)frameToRender { |
+ if (![EAGLContext setCurrentContext:_context]) { |
+ return NO; |
+ } |
+ |
+ return _gles_renderer20->Render(*frameToRender); |
+} |
+ |
+- (BOOL)setCoordinatesForZOrder:(const float)zOrder |
+ Left:(const float)left |
+ Top:(const float)top |
+ Right:(const float)right |
+ Bottom:(const float)bottom { |
+ return _gles_renderer20->SetCoordinates(zOrder, left, top, right, bottom); |
+} |
+ |
+@end |