ifish/Ifish/controllers/IfishYooseeFile/IfishYooseeHelper/IfishYooseeP2PCore/OpenGLView.mm

1150 lines
36 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//
// OpenGLView.m
// iVideoCalls
//
// Created by Kiwaro Nigas on 12-12-4.
// Copyright (c) 2012年 xizue.com. All rights reserved.
//
#import "OpenGLView.h"
#import <QuartzCore/QuartzCore.h>
#import <OpenGLES/EAGLDrawable.h>
#import <OpenGLES/EAGL.h>
#import <OpenGLES/ES2/gl.h>
#import <OpenGLES/ES2/glext.h>
#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<OpenGLRenderer> {
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; i<h; i++)
memcpy(y + w * i, yuvframe->data[0] + yuvframe->linesize[0] * i, w);
for (i=0; i<h/2; i++)
memcpy(u + w / 2 * i, yuvframe->data[1] + yuvframe->linesize[1] * i, w / 2);
for (i=0; i<h/2; i++)
memcpy(v + w / 2 * i, yuvframe->data[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<NSUInteger>(w), static_cast<NSUInteger>(w/2), static_cast<NSUInteger>(w/2) }; //shengming modify
const NSUInteger heights[3] = { static_cast<NSUInteger>(h), static_cast<NSUInteger>(h / 2), static_cast<NSUInteger>(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表示应用进入后台因为进入后台不能执行glToUIImageOpenGL
* 所以从监控画面按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 <width * 4; x++)
{
// buffer2[(height - 1 - y) * height * 4 + x] = buffer[y * 4 * height + x];
_buffer2[(height - 1 - y) * width * 4 + x] = buffer[y * 4 * width + x];
}
}
CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, _buffer2, myDataLength, NULL);
//CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, buffer2, myDataLength, providerReleaseData);
// prep the ingredients
int bitsPerComponent = 8;
int bitsPerPixel = 32;
// int bytesPerRow = 4 * height;
int bytesPerRow = 4 * width;
CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB();
CGBitmapInfo bitmapInfo = kCGBitmapByteOrderDefault;
CGColorRenderingIntent renderingIntent = kCGRenderingIntentDefault;
// make the cgimage
CGImageRef imageRef = CGImageCreate(width, height, bitsPerComponent, bitsPerPixel, bytesPerRow, colorSpaceRef, bitmapInfo, provider, NULL, NO, renderingIntent);
// then make the uiimage from that
UIImage *retImg = [UIImage imageWithCGImage:imageRef];
CGImageRelease(imageRef);
CGColorSpaceRelease(colorSpaceRef);
CGDataProviderRelease(provider);
free(buffer);
//free(buffer2);
return retImg;
}
#pragma mark - ShapeWarp
- (void) setFullScreenHeight:(int)iheight width:(int)iwidth fullScreen:(int)isFullScreen;
{
if (self.isFisheyeDevice) {
_gles2RenderWidth = iwidth;
_gles2RenderHeith = iheight;
_shapeWarp.ChangeScreen(iwidth, iheight, isFullScreen);
}
}
- (void) setAccelerationX:(float)x Y:(float) y Z:(float)z
{
if (self.isFisheyeDevice) {
int k = 13;
x = k*x/2;
y = k*y+7;
z = k*z;
_shapeWarp.setTrackerQuat( x, y, z, 0);
}
}
//init data
- (void)initDataShapeWarpTextureWidth:(int)width textureHeight:(int)height windowWidth:(int)w_width windowHeight:(int)w_height installType:(int)installType deviceID:(int)deviceID fishEyeType:(int)fishEyeType{
NSString *strId = [[[UIDevice currentDevice] identifierForVendor] UUIDString];
const char * uuid = [strId UTF8String];
NSString *strSysVersion = [UIDevice currentDevice].systemVersion;
const char * cVersion = [strSysVersion UTF8String];
_shapeWarp.initData(width, height, w_width, w_height, installType, cVersion, deviceID, uuid, _uniformMatrix,fishEyeType);
}
// zoom in/out
- (void)setZoomInOpenGLView{
if (self.isFisheyeDevice) {
_shapeWarp.setZoomIN();
}
}
- (void)setZoomOutOpenGLView{
if (self.isFisheyeDevice) {
_shapeWarp.setZoomOut();
}
}
- (void)setZoomInOpenGLViewX:(float)x Y:(float)y{
if (self.isFisheyeDevice) {
_shapeWarp.setZoomIN(x, y);
}
}
- (void)setZoomOutOpenGLViewX:(float)x Y:(float)y{
if (self.isFisheyeDevice) {
_shapeWarp.setZoomOut(x, y);
}
}
//singalTap
- (void)singalTapInOpenGLView{
if (self.isFisheyeDevice) {
_shapeWarp.singalTap();
}
}
//setGestureMode
- (void)setGestureModeInOpenGLView:(int)mode{
if (self.isFisheyeDevice) {
_shapeWarp.setGestureMode(mode);
}
}
//setKeyStatus
- (void)setKeyStatusInOpenGLView:(int)key{
if (self.isFisheyeDevice) {
_shapeWarp.setKeyStatus(key);
}
}
//setFling
- (void)setFlingInOpenGLViewX:(float)x Y:(float)y{
if (self.isFisheyeDevice) {
_shapeWarp.setFling(x, y);
}
}
//setMoveStep
- (void)setMoveStepInOpenGLViewX:(float)x Y:(float)y dX:(float)dx dY:(float)dy{
if (self.isFisheyeDevice) {
_shapeWarp.setMoveStep(x, y, dx, dy);
}
}
//static void providerReleaseData(void *info, const void *data, size_t size)
//{
// NSLog(@"free buffer2");
// free((void *)data);
//}
-(void)releseromotViewSet{
if(self.captureFinishScreen && _isGetVideoFrame){
AppDelegate *del = (AppDelegate *)[UIApplication sharedApplication].delegate;
/*
* isGoBack = YES表示应用进入后台因为进入后台不能执行glToUIImageOpenGL
* 所以从监控画面按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 (_program) {
glDeleteProgram(_program);
_program = 0;
}
if ([EAGLContext currentContext] == _context) {
[EAGLContext setCurrentContext:nil];
}
if (_context) {
_context = nil;
}
}
//返回时获取最后一针
-(void)getLastImgGoback{
UIImage *image = [[UIImage alloc] initWithCGImage:[self glToUIImage].CGImage];
if (!image) {
return;
}
NSData *imgData = [NSData dataWithData:UIImagePNGRepresentation(image)];
NSString* contactid = [[P2PClient sharedClient] callId];
[Utils saveHeaderFileWithId:contactid data:imgData];
}
@end