Reputation: 1367
I'm working on an app that plays a video on an OpenGLES scenario using textures (iOS9 using Xcode 7.1.1. although I don't think this is relevant)
When I start playing the video it goes in a loop and runs out of memory causing the app crash. xCode just says "Lost connection with ------ iPhone" (Thanks Apple, nice help), but after looking in more depth...
And from Instruments (running "Leaks") I got:
Seems to be clear that the problem comes from the textures but I'm not being able to fix it.
Here is how I declare the vars:
// Points to an unmanaged texture manager object, which can access an OpenGL texture
private var texturePointer = UnsafeMutablePointer<CVOpenGLESTexture?>.alloc(1)
// Cache for managing the video texture pointers
private var videoTextureCachePointer = UnsafeMutablePointer<CVOpenGLESTextureCache?>.alloc(1)
And this is the rest of the code:
// Load an image buffer into OpenGL
private func loadImageTexture(pixelBuffer: CVPixelBuffer!) {
// If null, return for safety
if (pixelBuffer == nil) {
return;
}
// Get frame size
let frameWidth = CVPixelBufferGetWidth(pixelBuffer)
let frameHeight = CVPixelBufferGetHeight(pixelBuffer)
// Release previous frame: No longer valid on iOS9! <-I should be removing old frames!
//texturePointer.release()
// Periodic texture cache flush every frame
let videoTextureCache = videoTextureCachePointer.memory!
CVOpenGLESTextureCacheFlush(videoTextureCache, 0);
// Copy from CPU to GPU
glActiveTexture(GLenum(GL_TEXTURE0))
CVOpenGLESTextureCacheCreateTextureFromImage(
kCFAllocatorDefault,
videoTextureCache,
pixelBuffer,
nil,
GLenum(GL_TEXTURE_2D),
GLint(GL_RGBA),
GLsizei(frameWidth),
GLsizei(frameHeight),
GLenum(GL_BGRA),
GLenum(GL_UNSIGNED_BYTE),
0,
&texturePointer.memory)
// Extract texture
let videoTexture = texturePointer[0]!
let videoTextureId = CVOpenGLESTextureGetName(videoTexture)
imageTexture = videoTextureId
// Configure texture
glBindTexture(CVOpenGLESTextureGetTarget(videoTexture), CVOpenGLESTextureGetName(videoTexture));
glTexParameteri(GLenum(GL_TEXTURE_2D), GLenum(GL_TEXTURE_MIN_FILTER), GL_LINEAR);
glTexParameteri(GLenum(GL_TEXTURE_2D), GLenum(GL_TEXTURE_MAG_FILTER), GL_LINEAR);
glTexParameteri(GLenum(GL_TEXTURE_2D), GLenum(GL_TEXTURE_WRAP_S), GL_CLAMP_TO_EDGE);
glTexParameteri(GLenum(GL_TEXTURE_2D), GLenum(GL_TEXTURE_WRAP_T), GL_CLAMP_TO_EDGE);
}
I'm kind of new in OpenGL so I guess I am missing "HOW" and "WHERE" to release the previous frames.
I tried "glDeleteTextures" but not sure if this is the solution.
Upvotes: 2
Views: 1210
Reputation: 16794
There is no need to have multiple textures or any kind of cache. I suggest you to create a single texture of fixed (large enough) size for instance 2024x2024 with empty data (pass nil as data parameter). Then when you get the pixel buffer rather use glTexSubImage
to transfer the data at (0, 0 , videoWidth, videoHeight)
. Now your texture is filled, rewritten by pixel buffer data and is ready to be drawn. The texture coordinates need to be computed which are then (0, 0, videoWidth/textureWidth, videoHeight/textureHeight)
. That is pretty much it. If the leak persists it has nothing to do with the openGL. The texture should be deleted when you don't need it any more (when the video is done playing or never if you want to reuse it for other videos).
Upvotes: 1