FURenderRotate.m 35 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201
  1. //
  2. // FURenderRotate.m
  3. // FULiveDemo
  4. //
  5. // Created by ly on 16/11/2.
  6. // Copyright © 2016年 liuyang. All rights reserved.
  7. //
  8. #import "FURenderRotate.h"
  9. #import <OpenGLES/ES2/gl.h>
  10. #import <OpenGLES/ES2/glext.h>
  11. #include <sys/mman.h>
  12. #include <sys/stat.h>
  13. #define documentPath NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject
  14. #define STRINGIZE(x) #x
  15. #define STRINGIZE2(x) STRINGIZE(x)
  16. #define SHADER_STRING(text) @ STRINGIZE2(text)
  17. NSString *const kRotateYUVToRGBAFragmentShaderString = SHADER_STRING
  18. (
  19. varying highp vec2 textureCoordinate;
  20. uniform sampler2D luminanceTexture;
  21. uniform sampler2D chrominanceTexture;
  22. uniform mediump mat3 colorConversionMatrix;
  23. void main()
  24. {
  25. mediump vec3 yuv;
  26. lowp vec3 rgb;
  27. yuv.x = texture2D(luminanceTexture, textureCoordinate).r;
  28. yuv.yz = texture2D(chrominanceTexture, textureCoordinate).rg - vec2(0.5, 0.5);
  29. rgb = colorConversionMatrix * yuv;
  30. gl_FragColor = vec4(rgb, 1.0);
  31. }
  32. );
  33. NSString *const kRotateRGBAFragmentShaderString = SHADER_STRING
  34. (
  35. precision mediump float;
  36. uniform float h_threshold;
  37. uniform float h_scale0;
  38. uniform float x_delta0;
  39. uniform float h_scale1;
  40. uniform float type420;
  41. uniform float typeNv12;
  42. uniform float useSelfAlpha;
  43. varying highp vec2 textureCoordinate;
  44. uniform sampler2D inputImageTexture;
  45. void main()
  46. {
  47. if(type420!=1.0){
  48. if(useSelfAlpha == 1.0){
  49. gl_FragColor = texture2D(inputImageTexture, textureCoordinate);
  50. }else{
  51. gl_FragColor = vec4(texture2D(inputImageTexture, textureCoordinate).rgb, 1.0);
  52. }
  53. }else
  54. {
  55. highp vec2 st0;
  56. highp vec2 st1;
  57. highp vec2 st2;
  58. highp vec2 st3;
  59. highp vec4 m0;
  60. highp vec4 m1;
  61. float base;
  62. if(textureCoordinate.y<h_threshold){
  63. st0=textureCoordinate*vec2(1.0,h_scale0)+vec2((-1.5)*x_delta0,0.0);
  64. st1=st0+vec2(x_delta0,0.0);
  65. st2=st0+vec2(x_delta0*2.0,0.0);
  66. st3=st0+vec2(x_delta0*3.0,0.0);
  67. m0=vec4(0.299,0.587,0.114,0.0);
  68. m1=vec4(0.299,0.587,0.114,0.0);
  69. base=0.0;
  70. }else{
  71. st0=vec2(textureCoordinate.x,textureCoordinate.y-h_threshold)*vec2(1.0,h_scale1)+vec2((-1.0)*x_delta0,0.0);
  72. st1=st0;
  73. st2=st0+vec2(x_delta0*2.0,0.0);
  74. st3=st2;
  75. if(typeNv12==0.0){
  76. m0=vec4(0.499,-0.418,-0.0813,0.0);
  77. m1=vec4(-0.169,-0.331,0.499,0.0);
  78. }else{
  79. m0=vec4(-0.169,-0.331,0.499,0.0);
  80. m1=vec4(0.499,-0.418,-0.0813,0.0);
  81. }
  82. base=0.5;
  83. }
  84. gl_FragColor=vec4(
  85. dot(texture2D(inputImageTexture,st0),m0)+base,
  86. dot(texture2D(inputImageTexture,st1),m1)+base,
  87. dot(texture2D(inputImageTexture,st2),m0)+base,
  88. dot(texture2D(inputImageTexture,st3),m1)+base).bgra;
  89. }
  90. }
  91. );
  92. NSString *const kRotateVertexShaderString = SHADER_STRING
  93. (
  94. attribute vec4 position;
  95. attribute vec4 inputTextureCoordinate;
  96. varying vec2 textureCoordinate;
  97. void main()
  98. {
  99. gl_Position = position;
  100. textureCoordinate = inputTextureCoordinate.xy;
  101. }
  102. );
  103. NSString *const FURotatePointsFrgShaderString = SHADER_STRING
  104. (
  105. precision mediump float;
  106. varying highp vec4 fragmentColor;
  107. void main()
  108. {
  109. if (-smoothstep(0.48, 0.5, length(gl_PointCoord - vec2(0.5))) + 1.0 == 0.0) {
  110. discard;
  111. }
  112. gl_FragColor = fragmentColor;
  113. }
  114. );
  115. NSString *const FURotatePointsVtxShaderString = SHADER_STRING
  116. (
  117. attribute vec4 position;
  118. attribute float point_size;
  119. attribute vec4 inputColor;
  120. varying vec4 fragmentColor;
  121. void main()
  122. {
  123. gl_Position = position;
  124. gl_PointSize = point_size;
  125. fragmentColor = inputColor;
  126. }
  127. );
  128. enum
  129. {
  130. rgbPositionAttribute,
  131. rgbTextureCoordinateAttribute
  132. };
  133. enum
  134. {
  135. furgbaPositionAttribute,
  136. furgbaTextureCoordinateAttribute,
  137. fuPointSize,
  138. fuPointColor,
  139. };
  140. enum
  141. {
  142. yuvConversionPositionAttribute,
  143. yuvConversionTextureCoordinateAttribute
  144. };
  145. @interface FURenderRotate ()
  146. @property (nonatomic, strong) EAGLContext *mContext;
  147. @property (nonatomic, strong) EAGLContext *tmpContext;
  148. @property (nonatomic, assign) CVPixelBufferRef renderTarget;
  149. @property (nonatomic, assign) CVPixelBufferRef resizeRenderTarget;
  150. @property (nonatomic, assign) CVPixelBufferRef yuvRenderTarget;
  151. @property (nonatomic, assign) int rotateType ;
  152. @end
  153. static FURenderRotate *_shareRenderer = nil;
  154. @implementation FURenderRotate
  155. {
  156. GLuint program;
  157. GLuint rgbToYuvProgram;
  158. GLuint pointProgram;
  159. CVOpenGLESTextureRef _texture;
  160. CVOpenGLESTextureCacheRef _videoTextureCache;
  161. GLuint _frameBufferHandle;
  162. CVOpenGLESTextureRef renderTexture;
  163. GLint yuvConversionLuminanceTextureUniform, yuvConversionChrominanceTextureUniform;
  164. GLint yuvConversionMatrixUniform;
  165. GLint displayInputTextureUniform;
  166. int frameWidth;
  167. int frameHeight;
  168. int resizeFrameWidth;
  169. int resizeFrameHeight;
  170. GLuint _resizeFrameBufferHandle;
  171. CVOpenGLESTextureRef resizeRenderTexture;
  172. GLuint h_threshold_yUniform;
  173. GLuint h_scale0_yUniform;
  174. GLuint x_delta0_yUniform;
  175. GLuint h_scale1_yUniform;
  176. GLuint type420_yUniform;
  177. GLuint typeNv12_yUniform;
  178. GLuint useSelfAlphaUniform;
  179. }
  180. - (void)setBackCurrentContext
  181. {
  182. EAGLContext *tmp = [EAGLContext currentContext];
  183. if (self.tmpContext != tmp) {
  184. [EAGLContext setCurrentContext:self.tmpContext];
  185. }
  186. self.tmpContext = nil;
  187. }
  188. - (void)setUpCurrentContext
  189. {
  190. self.tmpContext = [EAGLContext currentContext];
  191. if (self.mContext && self.tmpContext != self.mContext) {
  192. if (![EAGLContext setCurrentContext:self.mContext]) {
  193. NSLog(@"FURenderRotate setCurrentContext failed");
  194. }
  195. }
  196. }
  197. - (void)setMContext:(EAGLContext *)mContext
  198. {
  199. if (!_mContext) {
  200. _mContext = mContext;
  201. [self setUpCurrentContext];
  202. [self setupGL];
  203. [self setBackCurrentContext];
  204. }else
  205. {
  206. NSLog(@"FURenderRotate setShareContext failed,because it has be setted");
  207. }
  208. }
  209. - (void)setup
  210. {
  211. // static dispatch_once_t onceToken;
  212. // dispatch_once(&onceToken, ^{
  213. //
  214. //// fuSetup(data, ardata, package, size);
  215. //
  216. // self.mContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
  217. //
  218. // });
  219. self.mContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
  220. }
  221. - (void)rotateBufferType:(int)aa{
  222. self.rotateType = aa;
  223. }
  224. - (void)setupGL
  225. {
  226. [self loadShadersRGB];
  227. [self loadShadersYUV];
  228. // Create CVOpenGLESTextureCacheRef for optimal CVPixelBufferRef to GLES texture conversion.
  229. if (!_videoTextureCache) {
  230. EAGLContext *context = self.mContext;
  231. if (!context) {
  232. context = [EAGLContext currentContext];
  233. NSAssert(context, @"Faceunity ERROR: EAGLContext currentContext is nil");
  234. }
  235. CVReturn err = CVOpenGLESTextureCacheCreate(kCFAllocatorDefault, NULL, context, NULL, &_videoTextureCache);
  236. if (err != noErr) {
  237. NSLog(@"Error at CVOpenGLESTextureCacheCreate %d", err);
  238. return;
  239. }
  240. }
  241. }
  242. - (void)setupBuffer
  243. {
  244. [self setUpCurrentContext];
  245. if (_frameBufferHandle) {
  246. glDeleteFramebuffers(1, &_frameBufferHandle);
  247. _frameBufferHandle = 0;
  248. }
  249. if (_renderTarget) {
  250. CVPixelBufferRelease(_renderTarget);
  251. _renderTarget = nil;
  252. }
  253. if (renderTexture) {
  254. CFRelease(renderTexture);
  255. renderTexture = nil;
  256. }
  257. if (!_frameBufferHandle) {
  258. glGenFramebuffers(1, &_frameBufferHandle);
  259. glBindFramebuffer(GL_FRAMEBUFFER, _frameBufferHandle);
  260. }
  261. CVOpenGLESTextureCacheCreateTextureFromImage (kCFAllocatorDefault,
  262. _videoTextureCache, self.renderTarget,
  263. NULL, // texture attributes
  264. GL_TEXTURE_2D,
  265. GL_RGBA, // opengl format
  266. frameWidth,
  267. frameHeight,
  268. GL_BGRA, // native iOS format
  269. GL_UNSIGNED_BYTE,
  270. 0,
  271. &renderTexture);
  272. glBindTexture(CVOpenGLESTextureGetTarget(renderTexture), CVOpenGLESTextureGetName(renderTexture));
  273. glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  274. glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  275. // glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 720, 1280, 0, GL_BGRA, GL_UNSIGNED_BYTE, 0);
  276. glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, CVOpenGLESTextureGetName(renderTexture), 0);
  277. glBindTexture(GL_TEXTURE_2D, 0);
  278. [self setBackCurrentContext];
  279. }
  280. - (void)setupResizeBuffer
  281. {
  282. [self setUpCurrentContext];
  283. if (_resizeFrameBufferHandle) {
  284. glDeleteFramebuffers(1, &_resizeFrameBufferHandle);
  285. _resizeFrameBufferHandle = 0;
  286. }
  287. if (_resizeRenderTarget) {
  288. CVPixelBufferRelease(_resizeRenderTarget);
  289. _resizeRenderTarget = nil;
  290. }
  291. if (resizeRenderTexture) {
  292. CFRelease(resizeRenderTexture);
  293. resizeRenderTexture = nil;
  294. }
  295. if (!_resizeFrameBufferHandle) {
  296. glGenFramebuffers(1, &_resizeFrameBufferHandle);
  297. glBindFramebuffer(GL_FRAMEBUFFER, _resizeFrameBufferHandle);
  298. }
  299. CVOpenGLESTextureCacheCreateTextureFromImage (kCFAllocatorDefault,
  300. _videoTextureCache, self.resizeRenderTarget,
  301. NULL, // texture attributes
  302. GL_TEXTURE_2D,
  303. GL_RGBA, // opengl format
  304. resizeFrameWidth,
  305. resizeFrameHeight,
  306. GL_BGRA, // native iOS format
  307. GL_UNSIGNED_BYTE,
  308. 0,
  309. &resizeRenderTexture);
  310. glBindTexture(CVOpenGLESTextureGetTarget(resizeRenderTexture), CVOpenGLESTextureGetName(resizeRenderTexture));
  311. glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  312. glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  313. // glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 720, 1280, 0, GL_BGRA, GL_UNSIGNED_BYTE, 0);
  314. glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, CVOpenGLESTextureGetName(resizeRenderTexture), 0);
  315. glBindTexture(GL_TEXTURE_2D, 0);
  316. [self setBackCurrentContext];
  317. }
  318. - (CVPixelBufferRef)renderTarget
  319. {
  320. if (!_renderTarget && !(frameWidth == 0 || frameHeight == 0)) {
  321. CFDictionaryRef empty; // empty value for attr value.
  322. CFMutableDictionaryRef attrs;
  323. empty = CFDictionaryCreate(kCFAllocatorDefault, // our empty IOSurface properties dictionary
  324. NULL,
  325. NULL,
  326. 0,
  327. &kCFTypeDictionaryKeyCallBacks,
  328. &kCFTypeDictionaryValueCallBacks);
  329. attrs = CFDictionaryCreateMutable(kCFAllocatorDefault,
  330. 1,
  331. &kCFTypeDictionaryKeyCallBacks,
  332. &kCFTypeDictionaryValueCallBacks);
  333. CFDictionarySetValue(attrs,
  334. kCVPixelBufferIOSurfacePropertiesKey,
  335. empty);
  336. CVReturn theError = CVPixelBufferCreate(kCFAllocatorDefault, frameWidth, frameHeight, kCVPixelFormatType_32BGRA, attrs, &_renderTarget);
  337. if (theError)
  338. {
  339. // NSLog(@"FBO size");
  340. }
  341. CFRelease(attrs);
  342. CFRelease(empty);
  343. }
  344. return _renderTarget;
  345. }
  346. - (CVPixelBufferRef)resizeRenderTarget
  347. {
  348. if (!_resizeRenderTarget && !(resizeFrameWidth == 0 || resizeFrameHeight == 0)) {
  349. CFDictionaryRef empty; // empty value for attr value.
  350. CFMutableDictionaryRef attrs;
  351. empty = CFDictionaryCreate(kCFAllocatorDefault, // our empty IOSurface properties dictionary
  352. NULL,
  353. NULL,
  354. 0,
  355. &kCFTypeDictionaryKeyCallBacks,
  356. &kCFTypeDictionaryValueCallBacks);
  357. attrs = CFDictionaryCreateMutable(kCFAllocatorDefault,
  358. 1,
  359. &kCFTypeDictionaryKeyCallBacks,
  360. &kCFTypeDictionaryValueCallBacks);
  361. CFDictionarySetValue(attrs,
  362. kCVPixelBufferIOSurfacePropertiesKey,
  363. empty);
  364. CVReturn theError = CVPixelBufferCreate(kCFAllocatorDefault, resizeFrameWidth, resizeFrameHeight, kCVPixelFormatType_32BGRA, attrs, &_resizeRenderTarget);
  365. if (theError)
  366. {
  367. // NSLog(@"FBO size");
  368. }
  369. CFRelease(attrs);
  370. CFRelease(empty);
  371. }
  372. return _resizeRenderTarget;
  373. }
  374. - (CVPixelBufferRef)yuvRenderTarget
  375. {
  376. if (!_yuvRenderTarget && !(frameWidth == 0 || frameHeight == 0)) {
  377. NSDictionary *pixelAttributes = @{(id)kCVPixelBufferIOSurfacePropertiesKey : @{}};
  378. CVReturn theError = CVPixelBufferCreate(kCFAllocatorDefault,
  379. frameWidth,
  380. frameHeight,
  381. kCVPixelFormatType_420YpCbCr8BiPlanarFullRange,
  382. (__bridge CFDictionaryRef)(pixelAttributes),
  383. &_yuvRenderTarget);
  384. if (theError)
  385. {
  386. // NSLog(@"FBO size");
  387. }
  388. }
  389. return _yuvRenderTarget;
  390. }
  391. - (CVPixelBufferRef)renderPixelBuffer:(CVPixelBufferRef)pixelBuffer withLandmarks:(float *)landmarks count:(int)count MAX:(BOOL)max
  392. {
  393. if (pixelBuffer == NULL) return pixelBuffer;
  394. [self setUpCurrentContext];
  395. if (!_videoTextureCache) {
  396. [self setupGL];
  397. NSLog(@"No video texture cache");
  398. // [self setBackCurrentContext];
  399. // return pixelBuffer;
  400. }
  401. OSType type = CVPixelBufferGetPixelFormatType(pixelBuffer);
  402. int renderframeWidth = (int)CVPixelBufferGetWidth(self.renderTarget);
  403. int renderframeHeight = (int)CVPixelBufferGetHeight(self.renderTarget);
  404. frameWidth = (int)CVPixelBufferGetWidth(pixelBuffer);
  405. frameHeight = (int)CVPixelBufferGetHeight(pixelBuffer);
  406. if (frameWidth > frameHeight){
  407. float tepm = frameWidth ;
  408. frameWidth = frameHeight;
  409. frameHeight = tepm;
  410. }
  411. if (frameHeight != renderframeHeight || frameWidth != renderframeWidth) {
  412. [self setupBuffer];
  413. // return pixelBuffer;
  414. }
  415. if (type == kCVPixelFormatType_32BGRA)
  416. {
  417. [self cleanUpTextures];
  418. int width = (int)CVPixelBufferGetWidth(pixelBuffer);
  419. int height = (int)CVPixelBufferGetHeight(pixelBuffer);
  420. CVReturn err = CVOpenGLESTextureCacheCreateTextureFromImage(kCFAllocatorDefault, _videoTextureCache, pixelBuffer, NULL, GL_TEXTURE_2D, GL_RGBA, width, height,GL_BGRA, GL_UNSIGNED_BYTE, 0, &_texture);
  421. if (!_texture || err) {
  422. NSLog(@"Camera CVOpenGLESTextureCacheCreateTextureFromImage failed (error: %d)", err);
  423. [self setBackCurrentContext];
  424. return pixelBuffer;
  425. }
  426. glBindTexture(GL_TEXTURE_2D, CVOpenGLESTextureGetName(_texture));
  427. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  428. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  429. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  430. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  431. CVPixelBufferLockBaseAddress(pixelBuffer, 0);
  432. int stride = (int)CVPixelBufferGetBytesPerRow(pixelBuffer);
  433. GLuint textureHandle = CVOpenGLESTextureGetName(_texture);
  434. CVPixelBufferUnlockBaseAddress(pixelBuffer, 0);
  435. glUseProgram(program);
  436. GLint preFBO;
  437. glGetIntegerv(GL_FRAMEBUFFER_BINDING, &preFBO);
  438. GLint port[4];
  439. glGetIntegerv(GL_VIEWPORT, port);
  440. glBindFramebuffer(GL_FRAMEBUFFER, _frameBufferHandle);
  441. // Set the view port to the entire view.
  442. glViewport(0, 0, frameWidth, frameHeight);
  443. glClearColor(0.1f, 0.0f, 0.0f, 1.0f);
  444. glClear(GL_COLOR_BUFFER_BIT);
  445. glActiveTexture(GL_TEXTURE4);
  446. glBindTexture(GL_TEXTURE_2D, textureHandle);
  447. glUniform1i(displayInputTextureUniform, 4);
  448. GLfloat vertices[] = {
  449. -1.0f, -1.0f,
  450. 1.0f, -1.0f,
  451. -1.0f, 1.0f,
  452. 1.0f, 1.0f,
  453. };
  454. // if (!CGSizeEqualToSize(customSize, CGSizeZero)) {
  455. // const float dH = (float)frameHeight / height;
  456. // const float dW = (float)frameWidth / width;
  457. // const float dd = MAX(dH, dW);
  458. // const float h = (height * dd / (float)frameHeight);
  459. // const float w = (width * dd / (float)frameWidth );
  460. //
  461. // vertices[0] = - w;
  462. // vertices[1] = - h;
  463. // vertices[2] = w;
  464. // vertices[3] = - h;
  465. // vertices[4] = - w;
  466. // vertices[5] = h;
  467. // vertices[6] = w;
  468. // vertices[7] = h;
  469. // }
  470. // 更新顶点数据
  471. glVertexAttribPointer(rgbPositionAttribute, 2, GL_FLOAT, 0, 0, vertices);
  472. glEnableVertexAttribArray(rgbPositionAttribute);
  473. GLfloat *quadTextureData;
  474. if (_rotateType == 0) {
  475. GLfloat quadTextureData0[] = {
  476. 0.0f, 0.0f,
  477. 1.0f, 0.0f,
  478. 0.0f, 1.0f,
  479. 1.0f, 1.0f,
  480. };
  481. quadTextureData = quadTextureData0;
  482. }
  483. if (_rotateType == 1) {
  484. GLfloat quadTextureData0[] = {
  485. 0.0f, 0.0f,
  486. 0.0f, 1.0f,
  487. 1.0f, 0.0f,
  488. 1.0f, 1.0f,
  489. };
  490. quadTextureData = quadTextureData0;
  491. }
  492. if (_rotateType == 2) {
  493. GLfloat quadTextureData0[] = {
  494. 1.0f, 0.0f,
  495. 0.0f, 0.0f,
  496. 1.0f, 1.0f,
  497. 0.0f, 1.0f,
  498. };
  499. quadTextureData = quadTextureData0;
  500. }
  501. if (_rotateType == 3) {
  502. GLfloat quadTextureData0[] = {
  503. 1.0f, 0.0f,
  504. 1.0f, 1.0f,
  505. 0.0f, 0.0f,
  506. 0.0f, 1.0f,
  507. };
  508. quadTextureData = quadTextureData0;
  509. }
  510. glVertexAttribPointer(rgbTextureCoordinateAttribute, 2, GL_FLOAT, 0, 0, quadTextureData);
  511. glEnableVertexAttribArray(rgbTextureCoordinateAttribute);
  512. glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
  513. glFinish();
  514. if (count) {
  515. [self prepareToDrawLandmarks:landmarks count:count MAX:max];
  516. }
  517. glBindFramebuffer(GL_FRAMEBUFFER, preFBO);
  518. glViewport(port[0], port[1], port[2], port[3]);
  519. // if (!readBack) {
  520. [self setBackCurrentContext];
  521. // CVPixelBufferLockBaseAddress(self.renderTarget, 0);
  522. return self.renderTarget;
  523. // }
  524. size_t h1 = CVPixelBufferGetHeight(self.renderTarget);
  525. int stride1 = (int)CVPixelBufferGetBytesPerRow(self.renderTarget);
  526. uint8_t *newImg = CVPixelBufferGetBaseAddress(self.renderTarget);
  527. CVPixelBufferLockBaseAddress(pixelBuffer, 0);
  528. uint8_t *oldImg = CVPixelBufferGetBaseAddress(pixelBuffer);
  529. memcpy(oldImg, newImg, stride1*h1);
  530. CVPixelBufferUnlockBaseAddress(pixelBuffer, 0);
  531. CVPixelBufferUnlockBaseAddress(self.renderTarget, 0);
  532. }
  533. [self setBackCurrentContext];
  534. return pixelBuffer;
  535. }
  536. - (void)prepareToDrawLandmarks:(float *)landmarks count:(int)count MAX:(BOOL)max
  537. {
  538. if (!pointProgram) {
  539. [self loadPointsShaders];
  540. }
  541. glUseProgram(pointProgram);
  542. count = count/2;
  543. float sizeData[count];
  544. float colorData[count * 4];
  545. for (int i = 0; i < count; i++)
  546. {
  547. //点的大小
  548. sizeData[i] = 10;
  549. //点的颜色
  550. colorData[4 * i] = 1.0;
  551. colorData[4 * i + 1] = .0;
  552. colorData[4 * i + 2] = .0;
  553. colorData[4 * i + 3] = .0;
  554. //转化坐标
  555. landmarks[2 * i] = (float)((2 * landmarks[2 * i] / frameWidth - 1));
  556. landmarks[2 * i + 1] = (float)(1 - 2 * landmarks[2 * i + 1] / frameHeight)*-1;
  557. }
  558. glEnableVertexAttribArray(fuPointSize);
  559. glVertexAttribPointer(fuPointSize, 1, GL_FLOAT, GL_FALSE, 0, sizeData);
  560. glEnableVertexAttribArray(GLKVertexAttribPosition);
  561. glVertexAttribPointer(GLKVertexAttribPosition, 2, GL_FLOAT, GL_FALSE, 0, (GLfloat *)landmarks);
  562. glEnableVertexAttribArray(fuPointColor);
  563. glVertexAttribPointer(fuPointColor, 4, GL_FLOAT, GL_FALSE, 0, colorData);
  564. glDrawArrays(GL_POINTS, 0, count);
  565. glFinish();
  566. }
  567. - (CVPixelBufferRef)getPixelBufferFromTexture:(int)texture textureSize:(CGSize)textureSize outputSize:(CGSize)outPutSize outputFormat:(int)outputFormat{
  568. return self.resizeRenderTarget;
  569. }
  570. - (CVPixelBufferRef)resizePixelBuffer:(CVPixelBufferRef)pixelBuffer resizeSize:(CGSize)resizeSize
  571. {
  572. if (pixelBuffer == NULL) return pixelBuffer;
  573. [self setUpCurrentContext];
  574. if (!_videoTextureCache) {
  575. [self setupGL];
  576. }
  577. OSType type = CVPixelBufferGetPixelFormatType(pixelBuffer);
  578. int renderframeWidth = (int)CVPixelBufferGetWidth(self.resizeRenderTarget);
  579. int renderframeHeight = (int)CVPixelBufferGetHeight(self.resizeRenderTarget);
  580. resizeFrameWidth = (int)CVPixelBufferGetWidth(pixelBuffer);
  581. resizeFrameHeight = (int)CVPixelBufferGetHeight(pixelBuffer);
  582. if (!CGSizeEqualToSize(resizeSize, CGSizeZero)) {
  583. if (type == kCVPixelFormatType_32BGRA)
  584. {
  585. resizeFrameWidth = resizeSize.width;
  586. resizeFrameHeight = resizeSize.height;
  587. }else
  588. {
  589. NSLog(@"该接口目前仅支持自定义BGRA格式的pixelBuffer的输出分辨率");
  590. return pixelBuffer;
  591. }
  592. }
  593. if (resizeFrameHeight != renderframeHeight || resizeFrameWidth != renderframeWidth) {
  594. [self setupResizeBuffer];
  595. }
  596. [self cleanUpTextures];
  597. int width = (int)CVPixelBufferGetWidth(pixelBuffer);
  598. int height = (int)CVPixelBufferGetHeight(pixelBuffer);
  599. CVReturn err = CVOpenGLESTextureCacheCreateTextureFromImage(kCFAllocatorDefault, _videoTextureCache, pixelBuffer, NULL, GL_TEXTURE_2D, GL_RGBA, width, height,GL_BGRA, GL_UNSIGNED_BYTE, 0, &_texture);
  600. if (!_texture || err) {
  601. NSLog(@"Camera CVOpenGLESTextureCacheCreateTextureFromImage failed (error: %d)", err);
  602. [self setBackCurrentContext];
  603. return pixelBuffer;
  604. }
  605. glBindTexture(GL_TEXTURE_2D, CVOpenGLESTextureGetName(_texture));
  606. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  607. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  608. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  609. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  610. GLuint textureHandle = CVOpenGLESTextureGetName(_texture);
  611. glUseProgram(program);
  612. GLint preFBO;
  613. glGetIntegerv(GL_FRAMEBUFFER_BINDING, &preFBO);
  614. GLint port[4];
  615. glGetIntegerv(GL_VIEWPORT, port);
  616. glBindFramebuffer(GL_FRAMEBUFFER, _resizeFrameBufferHandle);
  617. // Set the view port to the entire view.
  618. glViewport(0, 0, resizeFrameWidth, resizeFrameHeight);
  619. glClearColor(0.1f, 0.0f, 0.0f, 1.0f);
  620. glClear(GL_COLOR_BUFFER_BIT);
  621. glActiveTexture(GL_TEXTURE4);
  622. glBindTexture(GL_TEXTURE_2D, textureHandle);
  623. glUniform1i(displayInputTextureUniform, 4);
  624. GLfloat vertices[] = {
  625. -1.0f, -1.0f,
  626. 1.0f, -1.0f,
  627. -1.0f, 1.0f,
  628. 1.0f, 1.0f,
  629. };
  630. if (!CGSizeEqualToSize(resizeSize, CGSizeZero)) {
  631. const float dH = (float)resizeFrameHeight / height;
  632. const float dW = (float)resizeFrameWidth / width;
  633. const float dd = MAX(dH, dW);
  634. const float h = (height * dd / (float)resizeFrameHeight);
  635. const float w = (width * dd / (float)resizeFrameWidth);
  636. vertices[0] = - w;
  637. vertices[1] = - h;
  638. vertices[2] = w;
  639. vertices[3] = - h;
  640. vertices[4] = - w;
  641. vertices[5] = h;
  642. vertices[6] = w;
  643. vertices[7] = h;
  644. }
  645. // 更新顶点数据
  646. glVertexAttribPointer(rgbPositionAttribute, 2, GL_FLOAT, 0, 0, vertices);
  647. glEnableVertexAttribArray(rgbPositionAttribute);
  648. GLfloat quadTextureData[] = {
  649. 0.0f, 0.0f,
  650. 1.0f, 0.0f,
  651. 0.0f, 1.0f,
  652. 1.0f, 1.0f,
  653. };
  654. glVertexAttribPointer(rgbTextureCoordinateAttribute, 2, GL_FLOAT, 0, 0, quadTextureData);
  655. glEnableVertexAttribArray(rgbTextureCoordinateAttribute);
  656. glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
  657. glFinish();
  658. glBindFramebuffer(GL_FRAMEBUFFER, preFBO);
  659. glViewport(port[0], port[1], port[2], port[3]);
  660. [self setBackCurrentContext];
  661. return self.resizeRenderTarget;
  662. }
  663. - (void)dealloc
  664. {
  665. [self cleanUpTextures];
  666. if(_videoTextureCache) {
  667. CFRelease(_videoTextureCache);
  668. }
  669. }
  670. - (void)cleanUpTextures
  671. {
  672. if (_texture) {
  673. CFRelease(_texture);
  674. _texture = NULL;
  675. }
  676. // Periodic texture cache flush every frame
  677. CVOpenGLESTextureCacheFlush(_videoTextureCache, 0);
  678. }
  679. #pragma mark - OpenGL ES 2 shader compilation
  680. - (BOOL)loadShadersRGB
  681. {
  682. GLuint vertShader, fragShader;
  683. if (!program) {
  684. program = glCreateProgram();
  685. }
  686. // Create and compile the vertex shader.
  687. if (![self compileShader:&vertShader type:GL_VERTEX_SHADER string:kRotateVertexShaderString]) {
  688. NSLog(@"Failed to compile vertex shader");
  689. return NO;
  690. }
  691. // Create and compile fragment shader.
  692. if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER string:kRotateRGBAFragmentShaderString]) {
  693. NSLog(@"Failed to compile fragment shader");
  694. return NO;
  695. }
  696. // Attach vertex shader to program.
  697. glAttachShader(program, vertShader);
  698. // Attach fragment shader to program.
  699. glAttachShader(program, fragShader);
  700. // Bind attribute locations. This needs to be done prior to linking.
  701. glBindAttribLocation(program, rgbPositionAttribute, "position");
  702. glBindAttribLocation(program, rgbTextureCoordinateAttribute, "inputTextureCoordinate");
  703. // Link the program.
  704. if (![self linkProgram:program]) {
  705. NSLog(@"Failed to link program: %d", program);
  706. if (vertShader) {
  707. glDeleteShader(vertShader);
  708. vertShader = 0;
  709. }
  710. if (fragShader) {
  711. glDeleteShader(fragShader);
  712. fragShader = 0;
  713. }
  714. if (program) {
  715. glDeleteProgram(program);
  716. program = 0;
  717. }
  718. return NO;
  719. }
  720. // Get uniform locations.
  721. displayInputTextureUniform = glGetUniformLocation(program, "inputImageTexture");
  722. h_threshold_yUniform = glGetUniformLocation(program, "h_threshold");
  723. h_scale0_yUniform = glGetUniformLocation(program, "h_scale0");
  724. x_delta0_yUniform = glGetUniformLocation(program, "x_delta0");
  725. h_scale1_yUniform = glGetUniformLocation(program, "h_scale1");
  726. type420_yUniform = glGetUniformLocation(program, "type420");
  727. typeNv12_yUniform = glGetUniformLocation(program, "typeNv12");
  728. useSelfAlphaUniform = glGetUniformLocation(program, "useSelfAlpha");
  729. // Release vertex and fragment shaders.
  730. if (vertShader) {
  731. glDetachShader(program, vertShader);
  732. glDeleteShader(vertShader);
  733. }
  734. if (fragShader) {
  735. glDetachShader(program, fragShader);
  736. glDeleteShader(fragShader);
  737. }
  738. return YES;
  739. }
  740. - (BOOL)loadPointsShaders
  741. {
  742. GLuint vertShader, fragShader;
  743. pointProgram = glCreateProgram();
  744. // Create and compile the vertex shader.
  745. if (![self compileShader:&vertShader type:GL_VERTEX_SHADER string:FURotatePointsVtxShaderString]) {
  746. NSLog(@"Failed to compile vertex shader");
  747. return NO;
  748. }
  749. // Create and compile fragment shader.
  750. if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER string:FURotatePointsFrgShaderString]) {
  751. NSLog(@"Failed to compile fragment shader");
  752. return NO;
  753. }
  754. // Attach vertex shader to program.
  755. glAttachShader(pointProgram, vertShader);
  756. // Attach fragment shader to program.
  757. glAttachShader(pointProgram, fragShader);
  758. // Bind attribute locations. This needs to be done prior to linking.
  759. glBindAttribLocation(pointProgram, fuPointSize, "point_size");
  760. glBindAttribLocation(pointProgram, fuPointColor, "inputColor");
  761. // Link the program.
  762. if (![self linkProgram:pointProgram]) {
  763. NSLog(@"Failed to link program: %d", pointProgram);
  764. if (vertShader) {
  765. glDeleteShader(vertShader);
  766. vertShader = 0;
  767. }
  768. if (fragShader) {
  769. glDeleteShader(fragShader);
  770. fragShader = 0;
  771. }
  772. if (pointProgram) {
  773. glDeleteProgram(pointProgram);
  774. pointProgram = 0;
  775. }
  776. return NO;
  777. }
  778. // Release vertex and fragment shaders.
  779. if (vertShader) {
  780. glDetachShader(pointProgram, vertShader);
  781. glDeleteShader(vertShader);
  782. }
  783. if (fragShader) {
  784. glDetachShader(pointProgram, fragShader);
  785. glDeleteShader(fragShader);
  786. }
  787. return YES;
  788. }
  789. - (BOOL)loadShadersYUV
  790. {
  791. GLuint vertShader, fragShader;
  792. if (!rgbToYuvProgram) {
  793. rgbToYuvProgram = glCreateProgram();
  794. }
  795. // Create and compile the vertex shader.
  796. if (![self compileShader:&vertShader type:GL_VERTEX_SHADER string:kRotateVertexShaderString]) {
  797. NSLog(@"Failed to compile vertex shader");
  798. return NO;
  799. }
  800. // Create and compile fragment shader.
  801. if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER string:kRotateYUVToRGBAFragmentShaderString]) {
  802. NSLog(@"Failed to compile fragment shader");
  803. return NO;
  804. }
  805. // Attach vertex shader to rgbToYuvProgram.
  806. glAttachShader(rgbToYuvProgram, vertShader);
  807. // Attach fragment shader to rgbToYuvProgram.
  808. glAttachShader(rgbToYuvProgram, fragShader);
  809. // Bind attribute locations. This needs to be done prior to linking.
  810. glBindAttribLocation(rgbToYuvProgram, yuvConversionPositionAttribute, "position");
  811. glBindAttribLocation(rgbToYuvProgram, yuvConversionTextureCoordinateAttribute, "inputTextureCoordinate");
  812. // Link the rgbToYuvProgram.
  813. if (![self linkProgram:rgbToYuvProgram]) {
  814. NSLog(@"Failed to link program: %d", rgbToYuvProgram);
  815. if (vertShader) {
  816. glDeleteShader(vertShader);
  817. vertShader = 0;
  818. }
  819. if (fragShader) {
  820. glDeleteShader(fragShader);
  821. fragShader = 0;
  822. }
  823. if (rgbToYuvProgram) {
  824. glDeleteProgram(rgbToYuvProgram);
  825. rgbToYuvProgram = 0;
  826. }
  827. return NO;
  828. }
  829. // Get uniform locations.
  830. yuvConversionLuminanceTextureUniform = glGetUniformLocation(rgbToYuvProgram, "luminanceTexture");
  831. yuvConversionChrominanceTextureUniform = glGetUniformLocation(rgbToYuvProgram, "chrominanceTexture");
  832. yuvConversionMatrixUniform = glGetUniformLocation(rgbToYuvProgram, "colorConversionMatrix");
  833. // Release vertex and fragment shaders.
  834. if (vertShader) {
  835. glDetachShader(rgbToYuvProgram, vertShader);
  836. glDeleteShader(vertShader);
  837. }
  838. if (fragShader) {
  839. glDetachShader(rgbToYuvProgram, fragShader);
  840. glDeleteShader(fragShader);
  841. }
  842. glUseProgram(rgbToYuvProgram);
  843. return YES;
  844. }
  845. - (BOOL)compileShader:(GLuint *)shader type:(GLenum)type string:(NSString *)shaderString
  846. {
  847. GLint status;
  848. const GLchar *source;
  849. source = (GLchar *)[shaderString UTF8String];
  850. *shader = glCreateShader(type);
  851. glShaderSource(*shader, 1, &source, NULL);
  852. glCompileShader(*shader);
  853. #if defined(DEBUG)
  854. GLint logLength;
  855. glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength);
  856. if (logLength > 0) {
  857. GLchar *log = (GLchar *)malloc(logLength);
  858. glGetShaderInfoLog(*shader, logLength, &logLength, log);
  859. NSLog(@"Shader compile log:\n%s", log);
  860. free(log);
  861. }
  862. #endif
  863. glGetShaderiv(*shader, GL_COMPILE_STATUS, &status);
  864. if (status == 0) {
  865. glDeleteShader(*shader);
  866. return NO;
  867. }
  868. return YES;
  869. }
  870. - (BOOL)linkProgram:(GLuint)prog
  871. {
  872. GLint status;
  873. glLinkProgram(prog);
  874. #if defined(DEBUG)
  875. GLint logLength;
  876. glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength);
  877. if (logLength > 0) {
  878. GLchar *log = (GLchar *)malloc(logLength);
  879. glGetProgramInfoLog(prog, logLength, &logLength, log);
  880. NSLog(@"Program link log:\n%s", log);
  881. free(log);
  882. }
  883. #endif
  884. glGetProgramiv(prog, GL_LINK_STATUS, &status);
  885. if (status == 0) {
  886. return NO;
  887. }
  888. return YES;
  889. }
  890. - (BOOL)validateProgram:(GLuint)prog
  891. {
  892. GLint logLength, status;
  893. glValidateProgram(prog);
  894. glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength);
  895. if (logLength > 0) {
  896. GLchar *log = (GLchar *)malloc(logLength);
  897. glGetProgramInfoLog(prog, logLength, &logLength, log);
  898. NSLog(@"Program validate log:\n%s", log);
  899. free(log);
  900. }
  901. glGetProgramiv(prog, GL_VALIDATE_STATUS, &status);
  902. if (status == 0) {
  903. return NO;
  904. }
  905. return YES;
  906. }
  907. + (void)dealFrameTime:(void (^)(void))block
  908. {
  909. glFinish();
  910. CFAbsoluteTime startTime = CFAbsoluteTimeGetCurrent();
  911. block();
  912. static int numberOfFramesCaptured = 0;
  913. static CGFloat totalFrameTimeDuringCapture = 0;
  914. numberOfFramesCaptured++;
  915. if (numberOfFramesCaptured > 5)
  916. {
  917. glFinish();
  918. CFAbsoluteTime currentFrameTime = (CFAbsoluteTimeGetCurrent() - startTime);
  919. totalFrameTimeDuringCapture += currentFrameTime;
  920. CGFloat Average = (totalFrameTimeDuringCapture / (CGFloat)(numberOfFramesCaptured - 5)) * 1000.0;
  921. NSLog(@"Average frame time : %f ms", Average);
  922. NSLog(@"Current frame time : %f ms", 1000.0 * currentFrameTime);
  923. }
  924. }
  925. //+ (void)onCameraChange
  926. //{
  927. //// fuOnCameraChange();
  928. //}
  929. //
  930. //+ (void)OnDeviceLost;
  931. //{
  932. // [self setUpCurrentContext];
  933. //
  934. //// fuOnDeviceLost();
  935. //
  936. // [self setBackCurrentContext];
  937. //}
  938. @end