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