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