blob: e259cee193a054f359f981c9b7e2465c304a54e6 [file] [log] [blame]
magjed15f0c682017-04-27 01:26:33 -07001/*
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 "RTCNV12TextureCache.h"
12
13#import "WebRTC/RTCVideoFrame.h"
14
15@implementation RTCNV12TextureCache {
16 CVOpenGLESTextureCacheRef _textureCache;
17 CVOpenGLESTextureRef _yTextureRef;
18 CVOpenGLESTextureRef _uvTextureRef;
19}
20
21- (GLuint)yTexture {
22 return CVOpenGLESTextureGetName(_yTextureRef);
23}
24
25- (GLuint)uvTexture {
26 return CVOpenGLESTextureGetName(_uvTextureRef);
27}
28
29- (instancetype)initWithContext:(EAGLContext *)context {
30 if (self = [super init]) {
31 CVReturn ret = CVOpenGLESTextureCacheCreate(
32 kCFAllocatorDefault, NULL,
33#if COREVIDEO_USE_EAGLCONTEXT_CLASS_IN_API
34 context,
35#else
36 (__bridge void *)context,
37#endif
38 NULL, &_textureCache);
39 if (ret != kCVReturnSuccess) {
40 self = nil;
41 }
42 }
43 return self;
44}
45
46- (BOOL)loadTexture:(CVOpenGLESTextureRef *)textureOut
47 pixelBuffer:(CVPixelBufferRef)pixelBuffer
48 planeIndex:(int)planeIndex
49 pixelFormat:(GLenum)pixelFormat {
50 const int width = CVPixelBufferGetWidthOfPlane(pixelBuffer, planeIndex);
51 const int height = CVPixelBufferGetHeightOfPlane(pixelBuffer, planeIndex);
52
53 if (*textureOut) {
54 CFRelease(*textureOut);
55 *textureOut = nil;
56 }
57 CVReturn ret = CVOpenGLESTextureCacheCreateTextureFromImage(
58 kCFAllocatorDefault, _textureCache, pixelBuffer, NULL, GL_TEXTURE_2D, pixelFormat, width,
59 height, pixelFormat, GL_UNSIGNED_BYTE, planeIndex, textureOut);
60 if (ret != kCVReturnSuccess) {
61 CFRelease(*textureOut);
62 *textureOut = nil;
63 return NO;
64 }
65 NSAssert(CVOpenGLESTextureGetTarget(*textureOut) == GL_TEXTURE_2D,
66 @"Unexpected GLES texture target");
67 glBindTexture(GL_TEXTURE_2D, CVOpenGLESTextureGetName(*textureOut));
68 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
69 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
70 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
71 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
72 return YES;
73}
74
75- (BOOL)uploadFrameToTextures:(RTCVideoFrame *)frame {
76 CVPixelBufferRef pixelBuffer = frame.nativeHandle;
77 NSParameterAssert(pixelBuffer);
78 return [self loadTexture:&_yTextureRef
79 pixelBuffer:pixelBuffer
80 planeIndex:0
81 pixelFormat:GL_LUMINANCE] &&
82 [self loadTexture:&_uvTextureRef
83 pixelBuffer:pixelBuffer
84 planeIndex:1
85 pixelFormat:GL_LUMINANCE_ALPHA];
86}
87
88- (void)releaseTextures {
89 if (_uvTextureRef) {
90 CFRelease(_uvTextureRef);
91 _uvTextureRef = nil;
92 }
93 if (_yTextureRef) {
94 CFRelease(_yTextureRef);
95 _yTextureRef = nil;
96 }
97}
98
99- (void)dealloc {
100 [self releaseTextures];
101 if (_textureCache) {
102 CFRelease(_textureCache);
103 _textureCache = nil;
104 }
105}
106
107@end
108