Home | History | Annotate | Download | only in ios
      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 
     18 using 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