iOS OpenGLES内存泄漏

时间:2015-11-12 21:12:17

标签: ios xcode swift opengl-es

我正在开发一个应用在OpenGLES场景中使用纹理播放视频的应用

当我开始播放视频时,它进入循环并耗尽内存导致应用程序崩溃。 xCode只是说“与------ iPhone失去联系”(感谢Apple,很好的帮助),但是在深入了解之后......

从xCode我得到了这个: enter image description here

从仪器(运行“Leaks”)我得到: enter image description here

似乎很清楚问题来自纹理,但我无法修复它。

以下是我宣布变种的方法:

// 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)

这是代码的其余部分:

// 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);

}

我是OpenGL的新手,所以我想我错过了“HOW”和“WHERE”来释放以前的帧。

我尝试了“glDeleteTextures”,但不确定这是否是解决方案。

1 个答案:

答案 0 :(得分:1)

不需要多个纹理或任何类型的缓存。我建议你创建一个固定(足够大)大小的单个纹理,例如2024x2024,带有空数据(传递nil作为数据参数)。然后,当您获得像素缓冲区时,请使用glTexSubImage(0, 0 , videoWidth, videoHeight)传输数据。现在,您的纹理已填充,由像素缓冲区数据重写,可以绘制。需要计算纹理坐标,然后(0, 0, videoWidth/textureWidth, videoHeight/textureHeight)。这就是它。如果泄漏持续存在,则与openGL无关。如果你不再需要它(当视频完成播放时,或者如果你想将其重复用于其他视频,则应删除纹理)。