关于GPUImage 两路输入 其中一路为 GPUImagePicture 的 问题的详细解析


情况1:

GPUImagePicture -> 添加到1

此时调用不会crash

GPUImageMovie -> 添加到0


在GPUImageTwoInputFilter中


由于纹理1为GPUImagePicture

- (void)setInputFramebuffer:(GPUImageFramebuffer *)newInputFramebuffer atIndex:(NSInteger)textureIndex;
{
(textureIndex == 0)
    {
;
;
[firstInputFramebuffer lock];
    }
    else
    {
;
[secondInputFramebuffer lock];
    }
}

因此此方法对于的secondInputFramebuffer只会在GPUImagePicture调用processImage时调用一次,因此在GPUImageMovie调用setInputFramebuffer方法时

textureIndex始终为0,既[secondInputFramebuffer lock];一直没有调用的机会。


在调用- (void)renderToTextureWithVertices:(const GLfloat *)vertices textureCoordinates:(const GLfloat *)textureCoordinates;方法时

有:

[firstInputFramebuffer unlock];
[secondInputFramebuffer unlock];//此时由于secondInputFramebuffer为GPUImagePicture的secondInputFramebuffer,而GPUImagePicture的secondInputFramebuffer已经调用了
[outputFramebuffer disableReferenceCounting];取消了outputFramebuffer的引用计数

在调用 [secondInputFramebuffer unlock];时有 此时不会crash

- (void)unlock;
{
(referenceCountingDisabled)
    {
;
    }
 …
}


情况2:

GPUImagePicture -> GPUImageFilter ->(各种滤镜组合) … ->添加到1

此时调用会crash

GPUImageMovie -> 添加到0


在GPUImageTwoInputFilter中


由于纹理1为GPUImagePicture

- (void)setInputFramebuffer:(GPUImageFramebuffer *)newInputFramebuffer atIndex:(NSInteger)textureIndex;
{
(textureIndex == 0)
    {
;
;
[firstInputFramebuffer lock];
    }
    else
    {
;
[secondInputFramebuffer lock];
    }
}

因此此方法对于的secondInputFramebuffer只会在GPUImagePicture调用processImage时调用一次,因此在GPUImageMovie调用setInputFramebuffer方法时

textureIndex始终为0,既[secondInputFramebuffer lock];一直没有调用的机会。


在调用- (void)renderToTextureWithVertices:(const GLfloat *)vertices textureCoordinates:(const GLfloat *)textureCoordinates;方法时

此处的secondInputFramebuffer已经不是GPUImagePicture的secondInputFramebuffer,此处的secondInputFramebuffer是GPUImagePicture后面添加的

GPUImageFilter的secondInputFramebuffer,而GPUImageFilter的secondInputFramebuffer的引用计数并没有调用[outputFramebuffer disableReferenceCounting]方法。

导致 在调用[secondInputFramebuffer unlock];方法时 触发framebufferReferenceCount 小于0 条件

NSAssert(framebufferReferenceCount > 0, @"Tried to overrelease a framebuffer, did you forget to call -useNextFrameForImageCapture before using -imageFromCurrentFramebuffer?");

此时 framebufferReferenceCount 会小于0,调试状态下直接crash。