Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(234)

Side by Side Diff: webrtc/sdk/objc/Framework/Classes/RTCI420TextureCache.mm

Issue 2842453002: ObjC: Split out I420 texture uploading into separate class (Closed)
Patch Set: Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright 2016 The WebRTC project authors. All Rights Reserved. 2 * Copyright 2017 The WebRTC project authors. All Rights Reserved.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license 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 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 6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may 7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree. 8 * be found in the AUTHORS file in the root of the source tree.
9 */ 9 */
10 10
11 #import "RTCShader.h" 11 #import "RTCI420TextureCache.h"
12
13 #import "RTCShader+Private.h"
12 14
13 #include <vector> 15 #include <vector>
14 16
15 #import "RTCShader+Private.h"
16 #import "WebRTC/RTCLogging.h"
17 #import "WebRTC/RTCVideoFrame.h"
18
19 #include "webrtc/base/optional.h"
20
21 // |kNumTextures| must not exceed 8, which is the limit in OpenGLES2. Two sets 17 // |kNumTextures| must not exceed 8, which is the limit in OpenGLES2. Two sets
sakal 2017/04/25 15:19:21 nit: I don't think this comment is relevant anymor
magjed_webrtc 2017/04/25 17:44:29 Done. I removed that sentence.
22 // of 3 textures are used here, one for each of the Y, U and V planes. Having 18 // of 3 textures are used here, one for each of the Y, U and V planes. Having
23 // two sets alleviates CPU blockage in the event that the GPU is asked to render 19 // two sets alleviates CPU blockage in the event that the GPU is asked to render
24 // to a texture that is already in use. 20 // to a texture that is already in use.
25 static const GLsizei kNumTextureSets = 2; 21 static const GLsizei kNumTextureSets = 2;
26 static const GLsizei kNumTexturesPerSet = 3; 22 static const GLsizei kNumTexturesPerSet = 3;
27 static const GLsizei kNumTextures = kNumTexturesPerSet * kNumTextureSets; 23 static const GLsizei kNumTextures = kNumTexturesPerSet * kNumTextureSets;
28 24
29 // Fragment shader converts YUV values from input textures into a final RGB 25 @implementation RTCI420TextureCache {
30 // pixel. The conversion formula is from http://www.fourcc.org/fccyvrgb.php.
31 static const char kI420FragmentShaderSource[] =
32 SHADER_VERSION
33 "precision highp float;"
34 FRAGMENT_SHADER_IN " vec2 v_texcoord;\n"
35 "uniform lowp sampler2D s_textureY;\n"
36 "uniform lowp sampler2D s_textureU;\n"
37 "uniform lowp sampler2D s_textureV;\n"
38 FRAGMENT_SHADER_OUT
39 "void main() {\n"
40 " float y, u, v, r, g, b;\n"
41 " y = " FRAGMENT_SHADER_TEXTURE "(s_textureY, v_texcoord).r;\n"
42 " u = " FRAGMENT_SHADER_TEXTURE "(s_textureU, v_texcoord).r;\n"
43 " v = " FRAGMENT_SHADER_TEXTURE "(s_textureV, v_texcoord).r;\n"
44 " u = u - 0.5;\n"
45 " v = v - 0.5;\n"
46 " r = y + 1.403 * v;\n"
47 " g = y - 0.344 * u - 0.714 * v;\n"
48 " b = y + 1.770 * u;\n"
49 " " FRAGMENT_SHADER_COLOR " = vec4(r, g, b, 1.0);\n"
50 " }\n";
51
52 @implementation RTCI420Shader {
53 BOOL _hasUnpackRowLength; 26 BOOL _hasUnpackRowLength;
54 GLint _currentTextureSet; 27 GLint _currentTextureSet;
55 // Handles for OpenGL constructs. 28 // Handles for OpenGL constructs.
56 GLuint _textures[kNumTextures]; 29 GLuint _textures[kNumTextures];
57 GLuint _i420Program; 30 // Used to create a non-padded plane for GPU upload when we receive padded fra mes.
58 GLuint _vertexArray;
59 GLuint _vertexBuffer;
60 GLint _ySampler;
61 GLint _uSampler;
62 GLint _vSampler;
63 // Store current rotation and only upload new vertex data when rotation
64 // changes.
65 rtc::Optional<RTCVideoRotation> _currentRotation;
66 // Used to create a non-padded plane for GPU upload when we receive padded
67 // frames.
68 std::vector<uint8_t> _planeBuffer; 31 std::vector<uint8_t> _planeBuffer;
69 } 32 }
70 33
34 - (GLuint)yTexture {
35 return _textures[_currentTextureSet * kNumTexturesPerSet];
36 }
37
38 - (GLuint)uTexture {
39 return _textures[_currentTextureSet * kNumTexturesPerSet + 1];
40 }
41
42 - (GLuint)vTexture {
43 return _textures[_currentTextureSet * kNumTexturesPerSet + 2];
44 }
45
71 - (instancetype)initWithContext:(GlContextType *)context { 46 - (instancetype)initWithContext:(GlContextType *)context {
72 if (self = [super init]) { 47 if (self = [super init]) {
73 #if TARGET_OS_IPHONE 48 #if TARGET_OS_IPHONE
74 _hasUnpackRowLength = (context.API == kEAGLRenderingAPIOpenGLES3); 49 _hasUnpackRowLength = (context.API == kEAGLRenderingAPIOpenGLES3);
75 #else 50 #else
76 _hasUnpackRowLength = YES; 51 _hasUnpackRowLength = YES;
77 #endif 52 #endif
78 glPixelStorei(GL_UNPACK_ALIGNMENT, 1); 53 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
79 if (![self setupI420Program] || ![self setupTextures] || 54
80 !RTCSetupVerticesForProgram(_i420Program, &_vertexBuffer, &_vertexArray) ) { 55 [self setupTextures];
81 RTCLog(@"Failed to initialize RTCI420Shader.");
82 self = nil;
83 }
84 } 56 }
85 return self; 57 return self;
86 } 58 }
87 59
88 - (void)dealloc { 60 - (void)dealloc {
89 glDeleteProgram(_i420Program);
90 glDeleteTextures(kNumTextures, _textures); 61 glDeleteTextures(kNumTextures, _textures);
91 glDeleteBuffers(1, &_vertexBuffer);
92 glDeleteVertexArrays(1, &_vertexArray);
93 } 62 }
94 63
95 - (BOOL)setupI420Program { 64 - (void)setupTextures {
96 _i420Program = RTCCreateProgramFromFragmentSource(kI420FragmentShaderSource);
97 if (!_i420Program) {
98 return NO;
99 }
100 _ySampler = glGetUniformLocation(_i420Program, "s_textureY");
101 _uSampler = glGetUniformLocation(_i420Program, "s_textureU");
102 _vSampler = glGetUniformLocation(_i420Program, "s_textureV");
103
104 return (_ySampler >= 0 && _uSampler >= 0 && _vSampler >= 0);
105 }
106
107 - (BOOL)setupTextures {
108 glGenTextures(kNumTextures, _textures); 65 glGenTextures(kNumTextures, _textures);
109 // Set parameters for each of the textures we created. 66 // Set parameters for each of the textures we created.
110 for (GLsizei i = 0; i < kNumTextures; i++) { 67 for (GLsizei i = 0; i < kNumTextures; i++) {
111 glBindTexture(GL_TEXTURE_2D, _textures[i]); 68 glBindTexture(GL_TEXTURE_2D, _textures[i]);
112 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 69 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
113 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 70 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
114 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 71 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
115 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 72 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
116 } 73 }
117 return YES;
118 }
119
120 - (BOOL)drawFrame:(RTCVideoFrame*)frame {
121 glUseProgram(_i420Program);
122 if (![self updateTextureDataForFrame:frame]) {
123 return NO;
124 }
125 #if !TARGET_OS_IPHONE
126 glBindVertexArray(_vertexArray);
127 #endif
128 glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer);
129 if (!_currentRotation || frame.rotation != *_currentRotation) {
130 _currentRotation = rtc::Optional<RTCVideoRotation>(frame.rotation);
131 RTCSetVertexData(*_currentRotation);
132 }
133 glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
134
135 return YES;
136 } 74 }
137 75
138 - (void)uploadPlane:(const uint8_t *)plane 76 - (void)uploadPlane:(const uint8_t *)plane
139 sampler:(GLint)sampler 77 texture:(GLuint)texture
140 offset:(GLint)offset
141 width:(size_t)width 78 width:(size_t)width
142 height:(size_t)height 79 height:(size_t)height
143 stride:(int32_t)stride { 80 stride:(int32_t)stride {
144 glActiveTexture(static_cast<GLenum>(GL_TEXTURE0 + offset)); 81 glBindTexture(GL_TEXTURE_2D, texture);
145 glBindTexture(GL_TEXTURE_2D, _textures[offset]);
146 82
147 // When setting texture sampler uniforms, the texture index is used not
148 // the texture handle.
149 glUniform1i(sampler, offset);
150 const uint8_t *uploadPlane = plane; 83 const uint8_t *uploadPlane = plane;
151 if ((size_t)stride != width) { 84 if ((size_t)stride != width) {
152 if (_hasUnpackRowLength) { 85 if (_hasUnpackRowLength) {
153 // GLES3 allows us to specify stride. 86 // GLES3 allows us to specify stride.
154 glPixelStorei(GL_UNPACK_ROW_LENGTH, stride); 87 glPixelStorei(GL_UNPACK_ROW_LENGTH, stride);
155 glTexImage2D(GL_TEXTURE_2D, 88 glTexImage2D(GL_TEXTURE_2D,
156 0, 89 0,
157 RTC_PIXEL_FORMAT, 90 RTC_PIXEL_FORMAT,
158 static_cast<GLsizei>(width), 91 static_cast<GLsizei>(width),
159 static_cast<GLsizei>(height), 92 static_cast<GLsizei>(height),
(...skipping 17 matching lines...) Expand all
177 0, 110 0,
178 RTC_PIXEL_FORMAT, 111 RTC_PIXEL_FORMAT,
179 static_cast<GLsizei>(width), 112 static_cast<GLsizei>(width),
180 static_cast<GLsizei>(height), 113 static_cast<GLsizei>(height),
181 0, 114 0,
182 RTC_PIXEL_FORMAT, 115 RTC_PIXEL_FORMAT,
183 GL_UNSIGNED_BYTE, 116 GL_UNSIGNED_BYTE,
184 uploadPlane); 117 uploadPlane);
185 } 118 }
186 119
187 - (BOOL)updateTextureDataForFrame:(RTCVideoFrame *)frame { 120 - (BOOL)uploadFrameToTextures:(RTCVideoFrame *)frame {
188 GLint textureOffset = _currentTextureSet * 3; 121 _currentTextureSet = (_currentTextureSet + 1) % kNumTextureSets;
189 NSAssert(textureOffset + 3 <= kNumTextures, @"invalid offset");
190 122
191 const int chromaWidth = (frame.width + 1) / 2; 123 const int chromaWidth = (frame.width + 1) / 2;
192 const int chromaHeight = (frame.height + 1) / 2; 124 const int chromaHeight = (frame.height + 1) / 2;
193 if (frame.strideY != frame.width || 125 if (frame.strideY != frame.width ||
194 frame.strideU != chromaWidth || 126 frame.strideU != chromaWidth ||
195 frame.strideV != chromaWidth) { 127 frame.strideV != chromaWidth) {
196 _planeBuffer.resize(frame.width * frame.height); 128 _planeBuffer.resize(frame.width * frame.height);
197 } 129 }
198 130
199 [self uploadPlane:frame.dataY 131 [self uploadPlane:frame.dataY
200 sampler:_ySampler 132 texture:self.yTexture
201 offset:textureOffset
202 width:frame.width 133 width:frame.width
203 height:frame.height 134 height:frame.height
204 stride:frame.strideY]; 135 stride:frame.strideY];
205 136
206 [self uploadPlane:frame.dataU 137 [self uploadPlane:frame.dataU
207 sampler:_uSampler 138 texture:self.uTexture
208 offset:textureOffset + 1
209 width:chromaWidth 139 width:chromaWidth
210 height:chromaHeight 140 height:chromaHeight
211 stride:frame.strideU]; 141 stride:frame.strideU];
212 142
213 [self uploadPlane:frame.dataV 143 [self uploadPlane:frame.dataV
214 sampler:_vSampler 144 texture:self.vTexture
215 offset:textureOffset + 2
216 width:chromaWidth 145 width:chromaWidth
217 height:chromaHeight 146 height:chromaHeight
218 stride:frame.strideV]; 147 stride:frame.strideV];
219 148
220 _currentTextureSet = (_currentTextureSet + 1) % kNumTextureSets;
221 return YES; 149 return YES;
222 } 150 }
223 151
224 @end 152 @end
OLDNEW
« no previous file with comments | « webrtc/sdk/objc/Framework/Classes/RTCI420TextureCache.h ('k') | webrtc/sdk/objc/Framework/Classes/RTCOpenGLDefines.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698