 Chromium Code Reviews
 Chromium Code Reviews Issue 2869143002:
  iOS: Add interface for injecting custom shaders  (Closed)
    
  
    Issue 2869143002:
  iOS: Add interface for injecting custom shaders  (Closed) 
  | OLD | NEW | 
|---|---|
| (Empty) | |
| 1 /* | |
| 2 * Copyright 2017 The WebRTC project authors. All Rights Reserved. | |
| 3 * | |
| 4 * Use of this source code is governed by a BSD-style license | |
| 5 * that can be found in the LICENSE file in the root of the source | |
| 6 * tree. An additional intellectual property rights grant can be found | |
| 7 * in the file PATENTS. All contributing project authors may | |
| 8 * be found in the AUTHORS file in the root of the source tree. | |
| 9 */ | |
| 10 | |
| 11 #import "RTCDefaultShaderDelegate.h" | |
| 12 | |
| 13 #if TARGET_OS_IPHONE | |
| 14 #import <OpenGLES/ES3/gl.h> | |
| 15 #else | |
| 16 #import <OpenGL/gl3.h> | |
| 17 #endif | |
| 18 | |
| 19 #import "RTCOpenGLDefines.h" | |
| 20 #import "RTCShader.h" | |
| 21 #import "WebRTC/RTCLogging.h" | |
| 22 | |
| 23 #include "webrtc/base/optional.h" | |
| 24 | |
| 25 static const int kYTextureUnit = 0; | |
| 26 static const int kUTextureUnit = 1; | |
| 27 static const int kVTextureUnit = 2; | |
| 28 static const int kUvTextureUnit = 1; | |
| 29 | |
| 30 // Fragment shader converts YUV values from input textures into a final RGB | |
| 31 // pixel. The conversion formula is from http://www.fourcc.org/fccyvrgb.php. | |
| 32 static const char kI420FragmentShaderSource[] = | |
| 33 SHADER_VERSION | |
| 34 "precision highp float;" | |
| 35 FRAGMENT_SHADER_IN " vec2 v_texcoord;\n" | |
| 36 "uniform lowp sampler2D s_textureY;\n" | |
| 37 "uniform lowp sampler2D s_textureU;\n" | |
| 38 "uniform lowp sampler2D s_textureV;\n" | |
| 39 FRAGMENT_SHADER_OUT | |
| 40 "void main() {\n" | |
| 41 " float y, u, v, r, g, b;\n" | |
| 42 " y = " FRAGMENT_SHADER_TEXTURE "(s_textureY, v_texcoord).r;\n" | |
| 43 " u = " FRAGMENT_SHADER_TEXTURE "(s_textureU, v_texcoord).r;\n" | |
| 44 " v = " FRAGMENT_SHADER_TEXTURE "(s_textureV, v_texcoord).r;\n" | |
| 45 " u = u - 0.5;\n" | |
| 46 " v = v - 0.5;\n" | |
| 47 " r = y + 1.403 * v;\n" | |
| 48 " g = y - 0.344 * u - 0.714 * v;\n" | |
| 49 " b = y + 1.770 * u;\n" | |
| 50 " " FRAGMENT_SHADER_COLOR " = vec4(r, g, b, 1.0);\n" | |
| 51 " }\n"; | |
| 52 | |
| 53 static const char kNV12FragmentShaderSource[] = | |
| 54 SHADER_VERSION | |
| 55 "precision mediump float;" | |
| 56 FRAGMENT_SHADER_IN " vec2 v_texcoord;\n" | |
| 57 "uniform lowp sampler2D s_textureY;\n" | |
| 58 "uniform lowp sampler2D s_textureUV;\n" | |
| 59 FRAGMENT_SHADER_OUT | |
| 60 "void main() {\n" | |
| 61 " mediump float y;\n" | |
| 62 " mediump vec2 uv;\n" | |
| 63 " y = " FRAGMENT_SHADER_TEXTURE "(s_textureY, v_texcoord).r;\n" | |
| 64 " uv = " FRAGMENT_SHADER_TEXTURE "(s_textureUV, v_texcoord).ra -\n" | |
| 65 " vec2(0.5, 0.5);\n" | |
| 66 " " FRAGMENT_SHADER_COLOR " = vec4(y + 1.403 * uv.y,\n" | |
| 67 " y - 0.344 * uv.x - 0.714 * uv.y,\n" | |
| 68 " y + 1.770 * uv.x,\n" | |
| 69 " 1.0);\n" | |
| 70 " }\n"; | |
| 71 | |
| 72 @implementation RTCDefaultShaderDelegate { | |
| 73 GLuint _vertexBuffer; | |
| 74 GLuint _vertexArray; | |
| 75 // Store current rotation and only upload new vertex data when rotation change s. | |
| 76 rtc::Optional<RTCVideoRotation> _currentRotation; | |
| 77 | |
| 78 GLuint _i420Program; | |
| 79 GLuint _nv12Program; | |
| 80 } | |
| 81 | |
| 82 - (void)dealloc { | |
| 83 glDeleteProgram(_i420Program); | |
| 84 glDeleteProgram(_nv12Program); | |
| 85 glDeleteBuffers(1, &_vertexBuffer); | |
| 86 glDeleteVertexArrays(1, &_vertexArray); | |
| 87 } | |
| 88 | |
| 89 - (BOOL)setupI420Program { | |
| 90 _i420Program = RTCCreateProgramFromFragmentSource(kI420FragmentShaderSource); | |
| 91 if (!_i420Program) { | |
| 92 return NO; | |
| 93 } | |
| 94 GLint ySampler = glGetUniformLocation(_i420Program, "s_textureY"); | |
| 95 GLint uSampler = glGetUniformLocation(_i420Program, "s_textureU"); | |
| 96 GLint vSampler = glGetUniformLocation(_i420Program, "s_textureV"); | |
| 97 | |
| 98 if (ySampler < 0 || uSampler < 0 || vSampler < 0) { | |
| 99 glDeleteProgram(_i420Program); | |
| 
sakal
2017/05/11 10:45:47
Log error?
 
magjed_webrtc
2017/05/11 12:38:06
Done.
 | |
| 100 _i420Program = 0; | |
| 101 return NO; | |
| 102 } | |
| 103 | |
| 104 glUseProgram(_i420Program); | |
| 105 glUniform1i(ySampler, kYTextureUnit); | |
| 106 glUniform1i(uSampler, kUTextureUnit); | |
| 107 glUniform1i(vSampler, kVTextureUnit); | |
| 108 | |
| 109 return YES; | |
| 110 } | |
| 111 | |
| 112 - (BOOL)setupNV12Program { | |
| 113 _nv12Program = RTCCreateProgramFromFragmentSource(kNV12FragmentShaderSource); | |
| 114 if (!_nv12Program) { | |
| 115 return NO; | |
| 116 } | |
| 117 GLint ySampler = glGetUniformLocation(_nv12Program, "s_textureY"); | |
| 118 GLint uvSampler = glGetUniformLocation(_nv12Program, "s_textureUV"); | |
| 119 | |
| 120 if (ySampler < 0 || uvSampler < 0) { | |
| 121 glDeleteProgram(_nv12Program); | |
| 122 _nv12Program = 0; | |
| 123 return NO; | |
| 124 } | |
| 125 | |
| 126 glUseProgram(_nv12Program); | |
| 127 glUniform1i(ySampler, kYTextureUnit); | |
| 128 glUniform1i(uvSampler, kUvTextureUnit); | |
| 129 | |
| 130 return YES; | |
| 131 } | |
| 132 | |
| 133 - (BOOL)prepareVertexBufferWithRotation:(RTCVideoRotation)rotation { | |
| 134 if (!_vertexBuffer && !RTCCreateVertexBuffer(&_vertexBuffer, &_vertexArray)) { | |
| 135 RTCLog(@"Failed to setup vertex buffer"); | |
| 136 return NO; | |
| 137 } | |
| 138 #if !TARGET_OS_IPHONE | |
| 139 glBindVertexArray(_vertexArray); | |
| 140 #endif | |
| 141 glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer); | |
| 142 if (!_currentRotation || rotation != *_currentRotation) { | |
| 143 _currentRotation = rtc::Optional<RTCVideoRotation>(rotation); | |
| 144 RTCSetVertexData(*_currentRotation); | |
| 145 } | |
| 146 return YES; | |
| 147 } | |
| 148 | |
| 149 - (void)videoView:(RTCVideoView *)videoView | |
| 150 didReceiveFrameWithRotation:(RTCVideoRotation)rotation | |
| 151 yPlane:(GLuint)yPlane | |
| 152 uPlane:(GLuint)uPlane | |
| 153 vPlane:(GLuint)vPlane { | |
| 154 if (![self prepareVertexBufferWithRotation:rotation]) { | |
| 155 return; | |
| 156 } | |
| 157 | |
| 158 if (!_i420Program && ![self setupI420Program]) { | |
| 159 RTCLog(@"Failed to setup I420 program"); | |
| 160 return; | |
| 161 } | |
| 162 | |
| 163 glUseProgram(_i420Program); | |
| 164 | |
| 165 glActiveTexture(static_cast<GLenum>(GL_TEXTURE0 + kYTextureUnit)); | |
| 166 glBindTexture(GL_TEXTURE_2D, yPlane); | |
| 167 | |
| 168 glActiveTexture(static_cast<GLenum>(GL_TEXTURE0 + kUTextureUnit)); | |
| 169 glBindTexture(GL_TEXTURE_2D, uPlane); | |
| 170 | |
| 171 glActiveTexture(static_cast<GLenum>(GL_TEXTURE0 + kVTextureUnit)); | |
| 172 glBindTexture(GL_TEXTURE_2D, vPlane); | |
| 173 | |
| 174 glDrawArrays(GL_TRIANGLE_FAN, 0, 4); | |
| 175 } | |
| 176 | |
| 177 - (void)videoView:(RTCVideoView *)videoView | |
| 178 didReceiveFrameWithRotation:(RTCVideoRotation)rotation | |
| 179 yPlane:(GLuint)yPlane | |
| 180 uvPlane:(GLuint)uvPlane { | |
| 181 if (![self prepareVertexBufferWithRotation:rotation]) { | |
| 182 return; | |
| 183 } | |
| 184 | |
| 185 if (!_nv12Program && ![self setupNV12Program]) { | |
| 186 RTCLog(@"Failed to setup NV12 shader"); | |
| 187 return; | |
| 188 } | |
| 189 | |
| 190 glUseProgram(_nv12Program); | |
| 191 | |
| 192 glActiveTexture(static_cast<GLenum>(GL_TEXTURE0 + kYTextureUnit)); | |
| 193 glBindTexture(GL_TEXTURE_2D, yPlane); | |
| 194 | |
| 195 glActiveTexture(static_cast<GLenum>(GL_TEXTURE0 + kUvTextureUnit)); | |
| 196 glBindTexture(GL_TEXTURE_2D, uvPlane); | |
| 197 | |
| 198 glDrawArrays(GL_TRIANGLE_FAN, 0, 4); | |
| 199 } | |
| 200 | |
| 201 @end | |
| OLD | NEW |