1146 lines
36 KiB
Plaintext
1146 lines
36 KiB
Plaintext
//
|
||
// 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 <GWP2P/GWP2P.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 = [[GWP2PClient sharedClient] getDeviceIDInAPMode];
|
||
// 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)];
|
||
int contactid = [[GWP2PClient sharedClient] getDeviceIDInAPMode];
|
||
int dwApContactID = [[AppDelegate sharedDefault] dwApContactID];
|
||
if (dwApContactID != 0)
|
||
{
|
||
contactid = dwApContactID;
|
||
}
|
||
[Utils saveHeaderFileWithId:[NSString stringWithFormat:@"%d",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表示应用进入后台,因为进入后台不能执行glToUIImage(OpenGL)
|
||
* 所以,从监控画面按Home键或锁屏键回到后台时,不截图(头像图片)
|
||
*/
|
||
if (!del.isGoBack) {
|
||
UIImage *image = [[UIImage alloc] initWithCGImage:[self glToUIImage].CGImage];
|
||
|
||
|
||
NSData *imgData = [NSData dataWithData:UIImagePNGRepresentation(image)];
|
||
int contactid = [[GWP2PClient sharedClient] getDeviceIDInAPMode];
|
||
int dwApContactID = [[AppDelegate sharedDefault] dwApContactID];
|
||
if (dwApContactID != 0)
|
||
{
|
||
contactid = dwApContactID;
|
||
}
|
||
[Utils saveHeaderFileWithId:[NSString stringWithFormat:@"%d",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)];
|
||
int contactid = [[GWP2PClient sharedClient] getDeviceIDInAPMode];
|
||
[Utils saveHeaderFileWithId:[NSString stringWithFormat:@"%d",contactid] data:imgData];
|
||
|
||
}
|
||
|
||
@end
|