// // OpenGLView.m // iVideoCalls // // Created by Kiwaro Nigas on 12-12-4. // Copyright (c) 2012年 xizue.com. All rights reserved. // #import "OpenGLView.h" #import #import #import #import #import #import "Constants.h" #import "Utils.h" #import "P2PClient.h" #import "AppDelegate.h" #import "ShapeRenderNotifyMsg.h" ////////////////////////////////////////////////////////// static float flPlayVideoWidth = 16; static float flPlayVideoHeight = 16; static float flPlayVideoLineSize = 16; #pragma mark - shaders #define STRINGIZE(x) #x #define STRINGIZE2(x) STRINGIZE(x) #define SHADER_STRING(text) @ STRINGIZE2(text) NSString *const vertexShaderString = SHADER_STRING ( attribute vec4 position; attribute vec2 texcoord; uniform mat4 modelViewProjectionMatrix; varying vec2 v_texcoord; void main() { gl_Position = modelViewProjectionMatrix * position; v_texcoord = texcoord.xy; } ); NSString *const rgbFragmentShaderString = SHADER_STRING ( varying highp vec2 v_texcoord; uniform sampler2D s_texture; void main() { gl_FragColor = texture2D(s_texture, v_texcoord); } ); NSString *const yuvFragmentShaderString = SHADER_STRING ( varying highp vec2 v_texcoord; uniform sampler2D s_texture_y; uniform sampler2D s_texture_u; uniform sampler2D s_texture_v; void main() { highp float y = texture2D(s_texture_y, v_texcoord).r; highp float u = texture2D(s_texture_u, v_texcoord).r - 0.5; highp float v = texture2D(s_texture_v, v_texcoord).r - 0.5; highp float r = y + 1.4075 * v; highp float g = y - 0.3455 * u - 0.7169 * v; highp float b = y + 1.779 * u; gl_FragColor = vec4(r,g,b,1.0); } ); static BOOL validateProgram(GLuint prog) { GLint status; glValidateProgram(prog); #ifdef DEBUG GLint logLength; glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); if (logLength > 0) { GLchar *log = (GLchar *)malloc(logLength); glGetProgramInfoLog(prog, logLength, &logLength, log); //DLog(@"Program validate log:\n%s", log); free(log); } #endif glGetProgramiv(prog, GL_VALIDATE_STATUS, &status); if (status == GL_FALSE) { //DLog(@"Failed to validate program %d", prog); return NO; } return YES; } static GLuint compileShader(GLenum type, NSString *shaderString) { GLint status; const GLchar *sources = (GLchar *)shaderString.UTF8String; GLuint shader = glCreateShader(type); if (shader == 0 || shader == GL_INVALID_ENUM) { DLog(@"Failed to create shader %d", type); return 0; } glShaderSource(shader, 1, &sources, NULL); glCompileShader(shader); #ifdef DEBUG GLint logLength; glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &logLength); if (logLength > 0) { GLchar *log = (GLchar *)malloc(logLength); glGetShaderInfoLog(shader, logLength, &logLength, log); //DLog(@"Shader compile log:\n%s", log); free(log); } #endif glGetShaderiv(shader, GL_COMPILE_STATUS, &status); if (status == GL_FALSE) { glDeleteShader(shader); DLog(@"Failed to compile shader:\n"); return 0; } return shader; } static void mat4f_LoadOrtho(float left, float right, float bottom, float top, float near, float far, float* mout) { float r_l = right - left; float t_b = top - bottom; float f_n = far - near; float tx = - (right + left) / (right - left); float ty = - (top + bottom) / (top - bottom); float tz = - (far + near) / (far - near); mout[0] = 2.0f / r_l; mout[1] = 0.0f; mout[2] = 0.0f; mout[3] = 0.0f; mout[4] = 0.0f; mout[5] = 2.0f / t_b; mout[6] = 0.0f; mout[7] = 0.0f; mout[8] = 0.0f; mout[9] = 0.0f; mout[10] = -2.0f / f_n; mout[11] = 0.0f; mout[12] = tx; mout[13] = ty; mout[14] = tz; mout[15] = 1.0f; } ////////////////////////////////////////////////////////// #pragma mark - frame renderers @interface OpenGLRenderer_YUV : NSObject { GLint _uniformSamplers[3]; GLuint _textures[3]; } @end @implementation OpenGLRenderer_YUV - (BOOL) isValid { return (_textures[0] != 0); } - (NSString *) fragmentShader { return yuvFragmentShaderString; } - (void) resolveUniforms: (GLuint) program { _uniformSamplers[0] = glGetUniformLocation(program, "s_texture_y"); _uniformSamplers[1] = glGetUniformLocation(program, "s_texture_u"); _uniformSamplers[2] = glGetUniformLocation(program, "s_texture_v"); } - (void) setFrame: (GAVFrame *) yuvframe { UInt8 *buf = (UInt8 *)malloc(yuvframe->width * yuvframe->height * 3 / 2); int w, h, i; UInt8 *y, *u, *v; w = yuvframe->width; h = yuvframe->height; y = buf; u = y + w * h; v = u + w * h / 4; for (i=0; idata[0] + yuvframe->linesize[0] * i, w); for (i=0; idata[1] + yuvframe->linesize[1] * i, w / 2); for (i=0; idata[2] + yuvframe->linesize[2] * i, w / 2); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); if (0 == _textures[0]) glGenTextures(3, _textures); const UInt8 *pixels[3] = { y, u, v }; // const NSUInteger widths[3] = { w, w/2, w/2 }; //shengming modify // const NSUInteger heights[3] = { h, h / 2, h / 2 }; const NSUInteger widths[3] = { static_cast(w), static_cast(w/2), static_cast(w/2) }; //shengming modify const NSUInteger heights[3] = { static_cast(h), static_cast(h / 2), static_cast(h / 2) }; for (int i = 0; i < 3; ++i) { glBindTexture(GL_TEXTURE_2D, _textures[i]); glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, (GLsizei) widths[i], (GLsizei) heights[i], 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, pixels[i]); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); } free(buf);//渲染模糊修复 } - (BOOL) prepareRender { if (_textures[0] == 0) return NO; for (int i = 0; i < 3; ++i) { glActiveTexture(GL_TEXTURE0 + i); glBindTexture(GL_TEXTURE_2D, _textures[i]); glUniform1i(_uniformSamplers[i], i); } //NSLog(@"prepareRender YES"); return YES; } - (void) dealloc { if (_textures[0]) glDeleteTextures(3, _textures); } @end ////////////////////////////////////////////////////////// #pragma mark - gl view GLfloat _vertices[8]= {-1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f}; static const GLfloat texCoords[8] = {0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f}; @interface OpenGLView () { ShapeWarp _shapeWarp; CGFloat _gles2RenderWidth; CGFloat _gles2RenderHeith; GLubyte *_buffer2; } @property (nonatomic, strong) UILabel *deviceTimeLabel; @property (nonatomic) BOOL isFisheyeDevice; @end @implementation OpenGLView @synthesize Initialized = _Initialized; + (Class) layerClass { return [CAEAGLLayer class]; } static GLfloat modelviewProj[16]; - (id)init { self.isFisheyeDevice = NO; mat4f_LoadOrtho(-1.0f, 1.0f, -1.0f, 1.0f, -1.0f, 1.0f, modelviewProj);//shengming if (self = [super init]) { DLog(@"Setup Open-GL renderer: YUV ..."); _renderer = [[OpenGLRenderer_YUV alloc] init]; DLog(@"OK"); // [self setFrame:[[UIScreen mainScreen] bounds]]; [self setFrame:CGRectMake(0, 0, 480, 300)]; if (self.isFisheyeDevice) {//鱼眼设备 [self setFrame:CGRectMake(0, 0, 320, 320)]; } CAEAGLLayer *eaglLayer = (CAEAGLLayer*) self.layer; eaglLayer.opaque = YES; eaglLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithBool:YES], kEAGLDrawablePropertyRetainedBacking, kEAGLColorFormatRGBA8, kEAGLDrawablePropertyColorFormat, nil]; self.contentScaleFactor = [UIScreen mainScreen].scale;//渲染模糊修复 _viewScale = [UIScreen mainScreen].scale;//渲染模糊修复 _context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; if (!_context || ![EAGLContext setCurrentContext:_context]) { DLog(@"failed to setup EAGLContext"); self = nil; return nil; } if (!self.isFisheyeDevice) {//非鱼眼设备 glGenFramebuffers(1, &_framebuffer); } glGenRenderbuffers(1, &_renderbuffer); if (self.isFisheyeDevice) {//鱼眼设备 glBindRenderbuffer(GL_RENDERBUFFER, _renderbuffer); glGenRenderbuffers(1, &_depthbuffer); glBindRenderbuffer(GL_RENDERBUFFER, _depthbuffer); glGenFramebuffers(1, &_framebuffer); } glBindFramebuffer(GL_FRAMEBUFFER, _framebuffer); if (self.isFisheyeDevice) {//鱼眼设备 int framebufferWidth, framebufferHeight; glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &framebufferWidth); glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &framebufferHeight); glBindRenderbuffer(GL_RENDERBUFFER, _depthbuffer); glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, self.bounds.size.width*_viewScale, self.bounds.size.height*_viewScale); } glBindRenderbuffer(GL_RENDERBUFFER, _renderbuffer); if (!self.isFisheyeDevice) {//非鱼眼设备 glBindRenderbuffer(GL_RENDERBUFFER, _renderbuffer); [_context renderbufferStorage:GL_RENDERBUFFER fromDrawable:(CAEAGLLayer*)self.layer]; } glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, _renderbuffer); if (self.isFisheyeDevice) {//鱼眼设备 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, _depthbuffer);// glEnable(GL_DEPTH_TEST); int a; glGetIntegerv(GL_DEPTH_BITS, &a); glBindRenderbuffer(GL_RENDERBUFFER, _renderbuffer); [_context renderbufferStorage:GL_RENDERBUFFER fromDrawable:eaglLayer]; } GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); if (status != GL_FRAMEBUFFER_COMPLETE) { DLog(@"failed to make complete framebuffer object %x", status); self = nil; return nil; } GLenum glError = glGetError(); if (GL_NO_ERROR != glError) { DLog(@"failed to setup GL %x", glError); self = nil; return nil; } if (![self loadShaders]) { self = nil; return nil; } //设备时间label UILabel *deviceTimeLabel = [[UILabel alloc] initWithFrame:CGRectMake(5.0, 5.0, 150.0, 20.0)]; deviceTimeLabel.backgroundColor = [UIColor clearColor]; deviceTimeLabel.textColor = [UIColor whiteColor]; deviceTimeLabel.font = [UIFont systemFontOfSize:10.0]; [deviceTimeLabel setHidden:YES]; [self addSubview:deviceTimeLabel]; self.deviceTimeLabel = deviceTimeLabel; DLog(@"Open-GL setup finished"); } NSString *strId = [[[UIDevice currentDevice] identifierForVendor] UUIDString]; const char * uuid = [strId UTF8String]; NSLog(@"设备唯一标识:|%@|", strId);//UUID,5.0后不可用 NSString *strSysVersion = [UIDevice currentDevice].systemVersion; const char * cVersion = [strSysVersion UTF8String]; NSLog(@"系统版本号:%@", strSysVersion);// e.g. @"4.0" NSString *contactId = [[P2PClient sharedClient] callId]; int callID = [contactId intValue]; NSLog(@"callid:%@", contactId);// e.g. @"4.0" if (self.isFisheyeDevice) {//can delete _shapeWarp.initData(self.bounds.size.width, self.bounds.size.height, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.width, _shapeWarp.SHAPE_CIRCLE, cVersion, callID, uuid, _uniformMatrix,_shapeWarp.FISHEYE_360); _shapeWarp.ChangeScreen(self.bounds.size.width, self.bounds.size.width, 0); _shapeWarp.setGestureMode(_shapeWarp.GESTRUE_MODE_FINGER); } return self; } - (id)initWithIsSupportFisheyeDevice:(BOOL)isSupportFisheyeDevice installType:(int)installType deviceID:(int)deviceID fishEyeType:(int)fishEyeType{ self.isFisheyeDevice = isSupportFisheyeDevice; mat4f_LoadOrtho(-1.0f, 1.0f, -1.0f, 1.0f, -1.0f, 1.0f, modelviewProj);//shengming if (self=[super init]) { DLog(@"Setup Open-GL renderer: YUV ..."); _renderer = [[OpenGLRenderer_YUV alloc] init]; DLog(@"OK"); // [self setFrame:[[UIScreen mainScreen] bounds]]; [self setFrame:CGRectMake(0, 0, 480, 300)]; // if (isSupportFisheyeDevice) {//鱼眼设备 // [self setFrame:CGRectMake(0, 0, 320, 320)]; // } CAEAGLLayer *eaglLayer = (CAEAGLLayer*) self.layer; eaglLayer.opaque = YES; eaglLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithBool:YES], kEAGLDrawablePropertyRetainedBacking, kEAGLColorFormatRGBA8, kEAGLDrawablePropertyColorFormat, nil]; self.contentScaleFactor = [UIScreen mainScreen].scale;//渲染模糊修复 _viewScale = [UIScreen mainScreen].scale;//渲染模糊修复 _context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; if (!_context || ![EAGLContext setCurrentContext:_context]) { DLog(@"failed to setup EAGLContext"); self = nil; return nil; } if (!isSupportFisheyeDevice) {//非鱼眼设备 glGenFramebuffers(1, &_framebuffer); } glGenRenderbuffers(1, &_renderbuffer); if (isSupportFisheyeDevice) {//鱼眼设备 glBindRenderbuffer(GL_RENDERBUFFER, _renderbuffer); glGenRenderbuffers(1, &_depthbuffer); glBindRenderbuffer(GL_RENDERBUFFER, _depthbuffer); glGenFramebuffers(1, &_framebuffer); } glBindFramebuffer(GL_FRAMEBUFFER, _framebuffer); if (isSupportFisheyeDevice) {//鱼眼设备 int framebufferWidth, framebufferHeight; glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &framebufferWidth); glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &framebufferHeight); glBindRenderbuffer(GL_RENDERBUFFER, _depthbuffer); glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, self.bounds.size.width*_viewScale, self.bounds.size.height*_viewScale); } glBindRenderbuffer(GL_RENDERBUFFER, _renderbuffer); if (!isSupportFisheyeDevice) {//非鱼眼设备 glBindRenderbuffer(GL_RENDERBUFFER, _renderbuffer); [_context renderbufferStorage:GL_RENDERBUFFER fromDrawable:(CAEAGLLayer*)self.layer]; } glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, _renderbuffer); if (isSupportFisheyeDevice) {//鱼眼设备 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, _depthbuffer);// glEnable(GL_DEPTH_TEST); int a; glGetIntegerv(GL_DEPTH_BITS, &a); glBindRenderbuffer(GL_RENDERBUFFER, _renderbuffer); [_context renderbufferStorage:GL_RENDERBUFFER fromDrawable:eaglLayer]; } GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); if (status != GL_FRAMEBUFFER_COMPLETE) { DLog(@"failed to make complete framebuffer object %x", status); self = nil; return nil; } GLenum glError = glGetError(); if (GL_NO_ERROR != glError) { DLog(@"failed to setup GL %x", glError); self = nil; return nil; } if (![self loadShaders]) { self = nil; return nil; } //设备时间label UILabel *deviceTimeLabel = [[UILabel alloc] initWithFrame:CGRectMake(5.0, 5.0, 150.0, 20.0)]; deviceTimeLabel.backgroundColor = [UIColor clearColor]; deviceTimeLabel.textColor = [UIColor whiteColor]; deviceTimeLabel.font = [UIFont systemFontOfSize:10.0]; [deviceTimeLabel setHidden:YES]; [self addSubview:deviceTimeLabel]; self.deviceTimeLabel = deviceTimeLabel; DLog(@"Open-GL setup finished"); } NSString *strId = [[[UIDevice currentDevice] identifierForVendor] UUIDString]; const char * uuid = [strId UTF8String]; NSLog(@"设备唯一标识:|%@|", strId);//UUID,5.0后不可用 NSString *strSysVersion = [UIDevice currentDevice].systemVersion; const char * cVersion = [strSysVersion UTF8String]; NSLog(@"系统版本号:%@", strSysVersion);// e.g. @"4.0" NSLog(@"callid:%d", deviceID);// e.g. @"4.0" if (self.isFisheyeDevice) { _shapeWarp.initData(self.bounds.size.width, self.bounds.size.height, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.width, installType, cVersion, deviceID, uuid, _uniformMatrix,fishEyeType); _shapeWarp.ChangeScreen(self.bounds.size.width, self.bounds.size.width, 0); _gles2RenderWidth = [UIScreen mainScreen].bounds.size.width; _gles2RenderHeith = [UIScreen mainScreen].bounds.size.width; _shapeWarp.setGestureMode(_shapeWarp.GESTRUE_MODE_FINGER); _shapeWarp.setNotifyFunction(&ShapeNotifyMsg); } return self; } - (void)dealloc { if(self.captureFinishScreen && _isGetVideoFrame){ AppDelegate *del = (AppDelegate *)[UIApplication sharedApplication].delegate; /* * isGoBack = YES表示应用进入后台,因为进入后台不能执行glToUIImage(OpenGL) * 所以,从监控画面按Home键或锁屏键回到后台时,不截图(头像图片) */ if (!del.isGoBack) { UIImage *image = [[UIImage alloc] initWithCGImage:[self glToUIImage].CGImage]; NSData *imgData = [NSData dataWithData:UIImagePNGRepresentation(image)]; NSString* contactid = [[P2PClient sharedClient] callId]; int dwApContactID = [[AppDelegate sharedDefault] dwApContactID]; if (dwApContactID != 0) { contactid = [NSString stringWithFormat:@"%d", dwApContactID]; } [Utils saveHeaderFileWithId:contactid data:imgData]; if (dwApContactID != 0) { [[NSNotificationCenter defaultCenter] postNotificationName:@"update head image" object:nil userInfo:nil]; } } } self.captureFinishScreen = NO; if (_renderer) { OpenGLRenderer_YUV* obj = (OpenGLRenderer_YUV*)_renderer; obj = nil; _renderer = nil; } if (_framebuffer) { glDeleteFramebuffers(1, &_framebuffer); _framebuffer = 0; } if (_renderbuffer) { glDeleteRenderbuffers(1, &_renderbuffer); _renderbuffer = 0; } if(_depthbuffer){ glDeleteRenderbuffers(1, &_depthbuffer); _depthbuffer = 0; } if (_program) { glDeleteProgram(_program); _program = 0; } if ([EAGLContext currentContext] == _context) { [EAGLContext setCurrentContext:nil]; } if (_context) { _context = nil; } if (_buffer2) { free(_buffer2); _buffer2 = NULL; } } - (BOOL)isvalid { if (_renderer) { return YES; } return NO; } - (void)layoutSubviews { @synchronized(self) { /* *1. isQuitMonitorInterface = YES表示避免退出监控时,因屏幕旋转(针对8.x,暂怀疑旋转所致)进入layoutSubviews *2. 所以退出监控时,不再执行layoutSubviews,保证正常截图 *3. 不知道为什么改成现在的进入监控界面方式,会出现这样的问题 */ if (!self.isQuitMonitorInterface) {//rtsp监控界面弹出修改 DLog(@"Setup play framebuffer..."); glBindRenderbuffer(GL_RENDERBUFFER, _renderbuffer); [_context renderbufferStorage:GL_RENDERBUFFER fromDrawable:(CAEAGLLayer*)self.layer]; glBindRenderbuffer(GL_RENDERBUFFER, _depthbuffer); glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, self.frame.size.width*_viewScale, self.frame.size.height*_viewScale); GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); if (status != GL_FRAMEBUFFER_COMPLETE) { DLog(@"failed to make complete framebuffer object %x", status); } flPlayVideoWidth = 16; ///shengming add ,reset w h flPlayVideoHeight = 16; flPlayVideoLineSize = 16; // [self updateVertices]; //shengming if (!_Initialized)//渲染模糊修复 { [self render:nil]; _Initialized = YES; } } } } - (void)setContentMode:(UIViewContentMode)contentMode { [super setContentMode:contentMode]; //[self updateVertices]; //shengming if (_renderer.isValid) if (!_Initialized) [self render:nil]; } - (BOOL)loadShaders { BOOL result = NO; GLuint vertShader = 0, fragShader = 0; DLog(@"Setup GL programm..."); _program = glCreateProgram(); vertShader = compileShader(GL_VERTEX_SHADER, vertexShaderString); if (!vertShader) goto exit; fragShader = compileShader(GL_FRAGMENT_SHADER, _renderer.fragmentShader); if (!fragShader) goto exit; glAttachShader(_program, vertShader); glAttachShader(_program, fragShader); glBindAttribLocation(_program, ATTRIBUTE_VERTEX, "position"); glBindAttribLocation(_program, ATTRIBUTE_TEXCOORD, "texcoord"); glLinkProgram(_program); GLint status; glGetProgramiv(_program, GL_LINK_STATUS, &status); if (status == GL_FALSE) { DLog(@"Failed to link program %d", _program); goto exit; } result = validateProgram(_program); _uniformMatrix = glGetUniformLocation(_program, "modelViewProjectionMatrix"); [_renderer resolveUniforms:_program]; exit: if (vertShader) glDeleteShader(vertShader); if (fragShader) glDeleteShader(fragShader); if (result) { DLog(@"OK"); } else { glDeleteProgram(_program); _program = 0; } return result; } - (void)render:(GAVFrame *)frame { @synchronized(self) { [EAGLContext setCurrentContext:_context]; if (self.isFisheyeDevice) {//鱼眼设备 int framebufferWidth, framebufferHeight; glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &framebufferWidth); glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &framebufferHeight); } glBindFramebuffer(GL_FRAMEBUFFER, _framebuffer);//shengming del if (self.isFisheyeDevice) {//鱼眼设备 //宽高 CGFloat w_h = self.bounds.size.width; //x坐标 CGFloat x = 0.0; //y坐标 CGFloat y = -(self.bounds.size.width-self.bounds.size.height)/2*_viewScale; glViewport(x, y, w_h*_viewScale, w_h*_viewScale); }else{ glViewport(0, 0, self.bounds.size.width*_viewScale, self.bounds.size.height*_viewScale);//渲染模糊修复 } glUseProgram(_program); if (frame && frame->data[0]) { [_renderer setFrame:frame]; } else { glClearColor(0.0f, 0.0f, 0.0f, 1.0f); if (self.isFisheyeDevice) {//鱼眼设备 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); }else{ glClear(GL_COLOR_BUFFER_BIT); } glUseProgram(_program); return ; } if ([_renderer prepareRender]) { GLfloat modelviewProj[16];//shengming del mat4f_LoadOrtho(-1.0f, 1.0f, -1.0f, 1.0f, -1.0f, 1.0f, modelviewProj);//shengming del if((frame->height != flPlayVideoHeight || frame->linesize[0] != flPlayVideoLineSize || frame->width != flPlayVideoWidth ) && frame->height != 0 && frame->width != 0 && flPlayVideoLineSize != 0 ) ///shengming { if (self.isFisheyeDevice) {//鱼眼设备 // _shapeWarp.drawself(); } flPlayVideoHeight = frame->height; flPlayVideoLineSize = frame->linesize[0]; flPlayVideoWidth = frame->width ; if (self.isFisheyeDevice) {//鱼眼设备 _shapeWarp.buildMaps(flPlayVideoLineSize, flPlayVideoHeight); }else{ glUniformMatrix4fv(_uniformMatrix, 1, GL_FALSE, modelviewProj); glVertexAttribPointer(ATTRIBUTE_VERTEX, 2, GL_FLOAT, 0, 0, _vertices); glEnableVertexAttribArray(ATTRIBUTE_VERTEX); glVertexAttribPointer(ATTRIBUTE_TEXCOORD, 2, GL_FLOAT, 0, 0, texCoords); glEnableVertexAttribArray(ATTRIBUTE_TEXCOORD); } } if (self.isFisheyeDevice) {//鱼眼设备 glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // glClear(GL_COLOR_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); _shapeWarp.drawself(); }else{ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); } //设备时间 dispatch_async(dispatch_get_main_queue(), ^{ if (self.isFisheyeDevice) {//鱼眼设备 [self.deviceTimeLabel setHidden:NO]; self.deviceTimeLabel.frame = CGRectMake(5.0-self.frame.origin.x, 5.0-self.frame.origin.y, 150.0, 20.0); [self.deviceTimeLabel setText:[self convertTimeByInterval:[NSString stringWithFormat:@"%llu",frame->pts/(1000*1000)]]]; }else{ [self.deviceTimeLabel setHidden:YES]; [self.deviceTimeLabel setText:@""]; } }); } glBindRenderbuffer(GL_RENDERBUFFER, _renderbuffer); //shengming del [_context presentRenderbuffer:GL_RENDERBUFFER]; if(self.isScreenShotting){ if (self.delegate && [self.delegate respondsToSelector:@selector(onScreenShotted:)]) { if (self.isFisheyeDevice) {//鱼眼设备 [self.delegate onScreenShotted:[self glToUIImage] timeInterval:[NSString stringWithFormat:@"%llu",frame->pts/(1000*1000)]]; }else{ [self.delegate onScreenShotted:[self glToUIImage]]; } } } self.isScreenShotting = NO; _isGetVideoFrame = YES;//渲染模糊修复 } } #pragma mark 秒转换成日期 -(NSString*)convertTimeByInterval:(NSString*)timeInterval{ NSDateFormatter *format = [[NSDateFormatter alloc] init]; [format setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0]];//这就是GMT+0时区了 NSDate *date = [NSDate dateWithTimeIntervalSince1970:timeInterval.intValue]; [format setDateFormat:@"yyyy-MM-dd HH:mm:ss"]; NSString *time = [format stringFromDate:date]; return time; } - (UIImage *)glToUIImage { NSInteger height = self.frame.size.height*_viewScale;//渲染模糊修复 NSInteger width = self.frame.size.width*_viewScale; if (flPlayVideoHeight !=0) { width = height*flPlayVideoWidth / flPlayVideoHeight; } if (self.isFisheyeDevice) {//鱼眼设备 width = _gles2RenderWidth*_viewScale; height = _gles2RenderHeith*_viewScale; } NSInteger myDataLength = width * height * 4; // allocate array and read pixels into it. GLubyte *buffer = (GLubyte *) malloc(myDataLength); glReadPixels(0, 0, (GLsizei)width, (GLsizei)height, GL_RGBA, GL_UNSIGNED_BYTE, buffer); if (_buffer2) { free(_buffer2); _buffer2 = NULL; } _buffer2 = (GLubyte *) malloc(myDataLength); for(int y = 0; y < height; y++) { for(int x = 0; x