blob: aab62d4363ab1c0e8f3bac0a95b3a23d050db836 [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) {
Aaron Goldenfb4e9bc2019-01-04 12:03:31 -080063 if (*textureOut) {
64 CFRelease(*textureOut);
65 *textureOut = nil;
66 }
magjed15f0c682017-04-27 01:26:33 -070067 return NO;
68 }
69 NSAssert(CVOpenGLESTextureGetTarget(*textureOut) == GL_TEXTURE_2D,
70 @"Unexpected GLES texture target");
71 glBindTexture(GL_TEXTURE_2D, CVOpenGLESTextureGetName(*textureOut));
72 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
73 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
74 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
75 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
76 return YES;
77}
78
79- (BOOL)uploadFrameToTextures:(RTCVideoFrame *)frame {
Anders Carlssone5960ce2017-06-22 15:26:30 +020080 NSAssert([frame.buffer isKindOfClass:[RTCCVPixelBuffer class]],
81 @"frame must be CVPixelBuffer backed");
82 RTCCVPixelBuffer *rtcPixelBuffer = (RTCCVPixelBuffer *)frame.buffer;
83 CVPixelBufferRef pixelBuffer = rtcPixelBuffer.pixelBuffer;
magjed15f0c682017-04-27 01:26:33 -070084 return [self loadTexture:&_yTextureRef
85 pixelBuffer:pixelBuffer
86 planeIndex:0
87 pixelFormat:GL_LUMINANCE] &&
88 [self loadTexture:&_uvTextureRef
89 pixelBuffer:pixelBuffer
90 planeIndex:1
91 pixelFormat:GL_LUMINANCE_ALPHA];
92}
93
94- (void)releaseTextures {
95 if (_uvTextureRef) {
96 CFRelease(_uvTextureRef);
97 _uvTextureRef = nil;
98 }
99 if (_yTextureRef) {
100 CFRelease(_yTextureRef);
101 _yTextureRef = nil;
102 }
103}
104
105- (void)dealloc {
106 [self releaseTextures];
107 if (_textureCache) {
108 CFRelease(_textureCache);
109 _textureCache = nil;
110 }
111}
112
113@end