• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
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 "base/RTCVideoFrame.h"
14#import "base/RTCVideoFrameBuffer.h"
15#import "components/video_frame_buffer/RTCCVPixelBuffer.h"
16
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    if (*textureOut) {
64      CFRelease(*textureOut);
65      *textureOut = nil;
66    }
67    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:(RTC_OBJC_TYPE(RTCVideoFrame) *)frame {
80  NSAssert([frame.buffer isKindOfClass:[RTC_OBJC_TYPE(RTCCVPixelBuffer) class]],
81           @"frame must be CVPixelBuffer backed");
82  RTC_OBJC_TYPE(RTCCVPixelBuffer) *rtcPixelBuffer = (RTC_OBJC_TYPE(RTCCVPixelBuffer) *)frame.buffer;
83  CVPixelBufferRef pixelBuffer = rtcPixelBuffer.pixelBuffer;
84  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
114