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

Side by Side Diff: webrtc/api/objc/RTCOpenGLVideoRenderer.mm

Issue 1542473003: Move Objective-C video renderers to webrtc/api/objc. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@updateI420Frame
Patch Set: Merge master Created 4 years, 11 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
« no previous file with comments | « webrtc/api/objc/RTCOpenGLVideoRenderer.h ('k') | webrtc/api/objc/RTCVideoRenderer.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * libjingle 2 * Copyright 2015 The WebRTC project authors. All Rights Reserved.
3 * Copyright 2014 Google Inc.
4 * 3 *
5 * Redistribution and use in source and binary forms, with or without 4 * Use of this source code is governed by a BSD-style license
6 * modification, are permitted provided that the following conditions are met: 5 * that can be found in the LICENSE file in the root of the source
7 * 6 * tree. An additional intellectual property rights grant can be found
8 * 1. Redistributions of source code must retain the above copyright notice, 7 * in the file PATENTS. All contributing project authors may
9 * this list of conditions and the following disclaimer. 8 * be found in the AUTHORS file in the root of the source tree.
10 * 2. Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 * 3. The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 9 */
27 10
28 #if !defined(__has_feature) || !__has_feature(objc_arc)
29 #error "This file requires ARC support."
30 #endif
31
32 #import "RTCOpenGLVideoRenderer.h" 11 #import "RTCOpenGLVideoRenderer.h"
33 12
34 #include <string.h> 13 #include <string.h>
35 14
36 #include "webrtc/base/scoped_ptr.h" 15 #include "webrtc/base/scoped_ptr.h"
37 16
38 #if TARGET_OS_IPHONE 17 #if TARGET_OS_IPHONE
39 #import <OpenGLES/ES3/gl.h> 18 #import <OpenGLES/ES3/gl.h>
40 #else 19 #else
41 #import <OpenGL/gl3.h> 20 #import <OpenGL/gl3.h>
42 #endif 21 #endif
43 22
44 #import "RTCI420Frame.h" 23 #import "RTCVideoFrame.h"
45 24
46 // TODO(tkchin): check and log openGL errors. Methods here return BOOLs in 25 // TODO(tkchin): check and log openGL errors. Methods here return BOOLs in
47 // anticipation of that happening in the future. 26 // anticipation of that happening in the future.
48 27
49 #if TARGET_OS_IPHONE 28 #if TARGET_OS_IPHONE
50 #define RTC_PIXEL_FORMAT GL_LUMINANCE 29 #define RTC_PIXEL_FORMAT GL_LUMINANCE
51 #define SHADER_VERSION 30 #define SHADER_VERSION
52 #define VERTEX_SHADER_IN "attribute" 31 #define VERTEX_SHADER_IN "attribute"
53 #define VERTEX_SHADER_OUT "varying" 32 #define VERTEX_SHADER_OUT "varying"
54 #define FRAGMENT_SHADER_IN "varying" 33 #define FRAGMENT_SHADER_IN "varying"
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
95 " u = u - 0.5;\n" 74 " u = u - 0.5;\n"
96 " v = v - 0.5;\n" 75 " v = v - 0.5;\n"
97 " r = y + 1.403 * v;\n" 76 " r = y + 1.403 * v;\n"
98 " g = y - 0.344 * u - 0.714 * v;\n" 77 " g = y - 0.344 * u - 0.714 * v;\n"
99 " b = y + 1.770 * u;\n" 78 " b = y + 1.770 * u;\n"
100 " " FRAGMENT_SHADER_COLOR " = vec4(r, g, b, 1.0);\n" 79 " " FRAGMENT_SHADER_COLOR " = vec4(r, g, b, 1.0);\n"
101 " }\n"; 80 " }\n";
102 81
103 // Compiles a shader of the given |type| with GLSL source |source| and returns 82 // Compiles a shader of the given |type| with GLSL source |source| and returns
104 // the shader handle or 0 on error. 83 // the shader handle or 0 on error.
105 GLuint CreateShader(GLenum type, const GLchar* source) { 84 GLuint CreateShader(GLenum type, const GLchar *source) {
106 GLuint shader = glCreateShader(type); 85 GLuint shader = glCreateShader(type);
107 if (!shader) { 86 if (!shader) {
108 return 0; 87 return 0;
109 } 88 }
110 glShaderSource(shader, 1, &source, NULL); 89 glShaderSource(shader, 1, &source, NULL);
111 glCompileShader(shader); 90 glCompileShader(shader);
112 GLint compileStatus = GL_FALSE; 91 GLint compileStatus = GL_FALSE;
113 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileStatus); 92 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileStatus);
114 if (compileStatus == GL_FALSE) { 93 if (compileStatus == GL_FALSE) {
115 glDeleteShader(shader); 94 glDeleteShader(shader);
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
157 136
158 // |kNumTextures| must not exceed 8, which is the limit in OpenGLES2. Two sets 137 // |kNumTextures| must not exceed 8, which is the limit in OpenGLES2. Two sets
159 // of 3 textures are used here, one for each of the Y, U and V planes. Having 138 // of 3 textures are used here, one for each of the Y, U and V planes. Having
160 // two sets alleviates CPU blockage in the event that the GPU is asked to render 139 // two sets alleviates CPU blockage in the event that the GPU is asked to render
161 // to a texture that is already in use. 140 // to a texture that is already in use.
162 static const GLsizei kNumTextureSets = 2; 141 static const GLsizei kNumTextureSets = 2;
163 static const GLsizei kNumTextures = 3 * kNumTextureSets; 142 static const GLsizei kNumTextures = 3 * kNumTextureSets;
164 143
165 @implementation RTCOpenGLVideoRenderer { 144 @implementation RTCOpenGLVideoRenderer {
166 #if TARGET_OS_IPHONE 145 #if TARGET_OS_IPHONE
167 EAGLContext* _context; 146 EAGLContext *_context;
168 #else 147 #else
169 NSOpenGLContext* _context; 148 NSOpenGLContext *_context;
170 #endif 149 #endif
171 BOOL _isInitialized; 150 BOOL _isInitialized;
172 NSUInteger _currentTextureSet; 151 NSUInteger _currentTextureSet;
173 // Handles for OpenGL constructs. 152 // Handles for OpenGL constructs.
174 GLuint _textures[kNumTextures]; 153 GLuint _textures[kNumTextures];
175 GLuint _program; 154 GLuint _program;
176 #if !TARGET_OS_IPHONE 155 #if !TARGET_OS_IPHONE
177 GLuint _vertexArray; 156 GLuint _vertexArray;
178 #endif 157 #endif
179 GLuint _vertexBuffer; 158 GLuint _vertexBuffer;
180 GLint _position; 159 GLint _position;
181 GLint _texcoord; 160 GLint _texcoord;
182 GLint _ySampler; 161 GLint _ySampler;
183 GLint _uSampler; 162 GLint _uSampler;
184 GLint _vSampler; 163 GLint _vSampler;
185 // Used to create a non-padded plane for GPU upload when we receive padded 164 // Used to create a non-padded plane for GPU upload when we receive padded
186 // frames. 165 // frames.
187 rtc::scoped_ptr<uint8_t[]> _planeBuffer; 166 rtc::scoped_ptr<uint8_t[]> _planeBuffer;
188 } 167 }
189 168
169 @synthesize lastDrawnFrame = _lastDrawnFrame;
170
190 + (void)initialize { 171 + (void)initialize {
191 // Disable dithering for performance. 172 // Disable dithering for performance.
192 glDisable(GL_DITHER); 173 glDisable(GL_DITHER);
193 } 174 }
194 175
195 #if TARGET_OS_IPHONE 176 #if TARGET_OS_IPHONE
196 - (instancetype)initWithContext:(EAGLContext*)context { 177 - (instancetype)initWithContext:(EAGLContext *)context {
197 #else 178 #else
198 - (instancetype)initWithContext:(NSOpenGLContext*)context { 179 - (instancetype)initWithContext:(NSOpenGLContext *)context {
199 #endif 180 #endif
200 NSAssert(context != nil, @"context cannot be nil"); 181 NSAssert(context != nil, @"context cannot be nil");
201 if (self = [super init]) { 182 if (self = [super init]) {
202 _context = context; 183 _context = context;
203 } 184 }
204 return self; 185 return self;
205 } 186 }
206 187
207 - (BOOL)drawFrame:(RTCI420Frame*)frame { 188 - (BOOL)drawFrame:(RTCVideoFrame *)frame {
208 if (!_isInitialized) { 189 if (!_isInitialized) {
209 return NO; 190 return NO;
210 } 191 }
211 if (_lastDrawnFrame == frame) { 192 if (_lastDrawnFrame == frame) {
212 return NO; 193 return NO;
213 } 194 }
214 [self ensureGLContext]; 195 [self ensureGLContext];
215 glClear(GL_COLOR_BUFFER_BIT); 196 glClear(GL_COLOR_BUFFER_BIT);
216 if (frame) { 197 if (frame) {
217 if (![self updateTextureSizesForFrame:frame] || 198 if (![self updateTextureSizesForFrame:frame] ||
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
318 glActiveTexture(GL_TEXTURE0 + i); 299 glActiveTexture(GL_TEXTURE0 + i);
319 glBindTexture(GL_TEXTURE_2D, _textures[i]); 300 glBindTexture(GL_TEXTURE_2D, _textures[i]);
320 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 301 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
321 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 302 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
322 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 303 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
323 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 304 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
324 } 305 }
325 return YES; 306 return YES;
326 } 307 }
327 308
328 - (BOOL)updateTextureSizesForFrame:(RTCI420Frame*)frame { 309 - (BOOL)updateTextureSizesForFrame:(RTCVideoFrame *)frame {
329 if (frame.height == _lastDrawnFrame.height && 310 if (frame.height == _lastDrawnFrame.height &&
330 frame.width == _lastDrawnFrame.width && 311 frame.width == _lastDrawnFrame.width &&
331 frame.chromaWidth == _lastDrawnFrame.chromaWidth && 312 frame.chromaWidth == _lastDrawnFrame.chromaWidth &&
332 frame.chromaHeight == _lastDrawnFrame.chromaHeight) { 313 frame.chromaHeight == _lastDrawnFrame.chromaHeight) {
333 return YES; 314 return YES;
334 } 315 }
335 GLsizei lumaWidth = frame.width; 316 GLsizei lumaWidth = frame.width;
336 GLsizei lumaHeight = frame.height; 317 GLsizei lumaHeight = frame.height;
337 GLsizei chromaWidth = frame.chromaWidth; 318 GLsizei chromaWidth = frame.chromaWidth;
338 GLsizei chromaHeight = frame.chromaHeight; 319 GLsizei chromaHeight = frame.chromaHeight;
(...skipping 22 matching lines...) Expand all
361 glTexImage2D(GL_TEXTURE_2D, 342 glTexImage2D(GL_TEXTURE_2D,
362 0, 343 0,
363 RTC_PIXEL_FORMAT, 344 RTC_PIXEL_FORMAT,
364 chromaWidth, 345 chromaWidth,
365 chromaHeight, 346 chromaHeight,
366 0, 347 0,
367 RTC_PIXEL_FORMAT, 348 RTC_PIXEL_FORMAT,
368 GL_UNSIGNED_BYTE, 349 GL_UNSIGNED_BYTE,
369 0); 350 0);
370 } 351 }
371 if (frame.yPitch != frame.width || frame.uPitch != frame.chromaWidth || 352 if ((NSUInteger)frame.yPitch != frame.width ||
372 frame.vPitch != frame.chromaWidth) { 353 (NSUInteger)frame.uPitch != frame.chromaWidth ||
354 (NSUInteger)frame.vPitch != frame.chromaWidth) {
373 _planeBuffer.reset(new uint8_t[frame.width * frame.height]); 355 _planeBuffer.reset(new uint8_t[frame.width * frame.height]);
374 } else { 356 } else {
375 _planeBuffer.reset(); 357 _planeBuffer.reset();
376 } 358 }
377 return YES; 359 return YES;
378 } 360 }
379 361
380 - (void)uploadPlane:(const uint8_t*)plane 362 - (void)uploadPlane:(const uint8_t *)plane
381 sampler:(GLint)sampler 363 sampler:(GLint)sampler
382 offset:(NSUInteger)offset 364 offset:(NSUInteger)offset
383 width:(NSUInteger)width 365 width:(size_t)width
384 height:(NSUInteger)height 366 height:(size_t)height
385 stride:(NSInteger)stride { 367 stride:(int32_t)stride {
386 glActiveTexture(GL_TEXTURE0 + offset); 368 glActiveTexture(GL_TEXTURE0 + offset);
387 // When setting texture sampler uniforms, the texture index is used not 369 // When setting texture sampler uniforms, the texture index is used not
388 // the texture handle. 370 // the texture handle.
389 glUniform1i(sampler, offset); 371 glUniform1i(sampler, offset);
390 #if TARGET_OS_IPHONE 372 #if TARGET_OS_IPHONE
391 BOOL hasUnpackRowLength = _context.API == kEAGLRenderingAPIOpenGLES3; 373 BOOL hasUnpackRowLength = _context.API == kEAGLRenderingAPIOpenGLES3;
392 #else 374 #else
393 BOOL hasUnpackRowLength = YES; 375 BOOL hasUnpackRowLength = YES;
394 #endif 376 #endif
395 const uint8_t* uploadPlane = plane; 377 const uint8_t *uploadPlane = plane;
396 if (stride != width) { 378 if ((size_t)stride != width) {
397 if (hasUnpackRowLength) { 379 if (hasUnpackRowLength) {
398 // GLES3 allows us to specify stride. 380 // GLES3 allows us to specify stride.
399 glPixelStorei(GL_UNPACK_ROW_LENGTH, stride); 381 glPixelStorei(GL_UNPACK_ROW_LENGTH, stride);
400 glTexImage2D(GL_TEXTURE_2D, 382 glTexImage2D(GL_TEXTURE_2D,
401 0, 383 0,
402 RTC_PIXEL_FORMAT, 384 RTC_PIXEL_FORMAT,
403 width, 385 width,
404 height, 386 height,
405 0, 387 0,
406 RTC_PIXEL_FORMAT, 388 RTC_PIXEL_FORMAT,
407 GL_UNSIGNED_BYTE, 389 GL_UNSIGNED_BYTE,
408 uploadPlane); 390 uploadPlane);
409 glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); 391 glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
410 return; 392 return;
411 } else { 393 } else {
412 // Make an unpadded copy and upload that instead. Quick profiling showed 394 // Make an unpadded copy and upload that instead. Quick profiling showed
413 // that this is faster than uploading row by row using glTexSubImage2D. 395 // that this is faster than uploading row by row using glTexSubImage2D.
414 uint8_t* unpaddedPlane = _planeBuffer.get(); 396 uint8_t *unpaddedPlane = _planeBuffer.get();
415 for (NSUInteger y = 0; y < height; ++y) { 397 for (size_t y = 0; y < height; ++y) {
416 memcpy(unpaddedPlane + y * width, plane + y * stride, width); 398 memcpy(unpaddedPlane + y * width, plane + y * stride, width);
417 } 399 }
418 uploadPlane = unpaddedPlane; 400 uploadPlane = unpaddedPlane;
419 } 401 }
420 } 402 }
421 glTexImage2D(GL_TEXTURE_2D, 403 glTexImage2D(GL_TEXTURE_2D,
422 0, 404 0,
423 RTC_PIXEL_FORMAT, 405 RTC_PIXEL_FORMAT,
424 width, 406 width,
425 height, 407 height,
426 0, 408 0,
427 RTC_PIXEL_FORMAT, 409 RTC_PIXEL_FORMAT,
428 GL_UNSIGNED_BYTE, 410 GL_UNSIGNED_BYTE,
429 uploadPlane); 411 uploadPlane);
430 } 412 }
431 413
432 - (BOOL)updateTextureDataForFrame:(RTCI420Frame*)frame { 414 - (BOOL)updateTextureDataForFrame:(RTCVideoFrame *)frame {
433 NSUInteger textureOffset = _currentTextureSet * 3; 415 NSUInteger textureOffset = _currentTextureSet * 3;
434 NSAssert(textureOffset + 3 <= kNumTextures, @"invalid offset"); 416 NSAssert(textureOffset + 3 <= kNumTextures, @"invalid offset");
435 417
436 [self uploadPlane:frame.yPlane 418 [self uploadPlane:frame.yPlane
437 sampler:_ySampler 419 sampler:_ySampler
438 offset:textureOffset 420 offset:textureOffset
439 width:frame.width 421 width:frame.width
440 height:frame.height 422 height:frame.height
441 stride:frame.yPitch]; 423 stride:frame.yPitch];
442 424
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
476 #endif 458 #endif
477 return NO; 459 return NO;
478 } 460 }
479 glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer); 461 glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer);
480 glBufferData(GL_ARRAY_BUFFER, sizeof(gVertices), gVertices, GL_DYNAMIC_DRAW); 462 glBufferData(GL_ARRAY_BUFFER, sizeof(gVertices), gVertices, GL_DYNAMIC_DRAW);
481 463
482 // Read position attribute from |gVertices| with size of 2 and stride of 4 464 // Read position attribute from |gVertices| with size of 2 and stride of 4
483 // beginning at the start of the array. The last argument indicates offset 465 // beginning at the start of the array. The last argument indicates offset
484 // of data within |gVertices| as supplied to the vertex buffer. 466 // of data within |gVertices| as supplied to the vertex buffer.
485 glVertexAttribPointer( 467 glVertexAttribPointer(
486 _position, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), (void*)0); 468 _position, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), (void *)0);
487 glEnableVertexAttribArray(_position); 469 glEnableVertexAttribArray(_position);
488 470
489 // Read texcoord attribute from |gVertices| with size of 2 and stride of 4 471 // Read texcoord attribute from |gVertices| with size of 2 and stride of 4
490 // beginning at the first texcoord in the array. The last argument indicates 472 // beginning at the first texcoord in the array. The last argument indicates
491 // offset of data within |gVertices| as supplied to the vertex buffer. 473 // offset of data within |gVertices| as supplied to the vertex buffer.
492 glVertexAttribPointer(_texcoord, 474 glVertexAttribPointer(_texcoord,
493 2, 475 2,
494 GL_FLOAT, 476 GL_FLOAT,
495 GL_FALSE, 477 GL_FALSE,
496 4 * sizeof(GLfloat), 478 4 * sizeof(GLfloat),
497 (void*)(2 * sizeof(GLfloat))); 479 (void *)(2 * sizeof(GLfloat)));
498 glEnableVertexAttribArray(_texcoord); 480 glEnableVertexAttribArray(_texcoord);
499 481
500 return YES; 482 return YES;
501 } 483 }
502 484
503 @end 485 @end
OLDNEW
« no previous file with comments | « webrtc/api/objc/RTCOpenGLVideoRenderer.h ('k') | webrtc/api/objc/RTCVideoRenderer.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698