BradLarson / GPUImage

An open source iOS framework for GPU-based image and video processing
http://www.sunsetlakesoftware.com/2012/02/12/introducing-gpuimage-framework
BSD 3-Clause "New" or "Revised" License
20.25k stars 4.61k forks source link

FrameBufferCache and GPUImageTwoInputFilter #1508

Open rued opened 10 years ago

rued commented 10 years ago

I have a problem with GPUImageTwoInputFilter:

This works fine: GPUImageVideoCamera -> GPUImageFilter -> GPUImageTwoInputFilter GPUImagePicture -> GPUImageTwoInputFilter

This doesn't: GPUImageVideoCamera -> GPUImageFilterA -> GPUImageTwoInputFilter GPUImagePicture -> GPUImageFilterB -> GPUImageTwoInputFilter

The latter gives me the "Tried to overrelease a frame buffer…" assertion. When I look at the call stack I see that the firstInputFrameBuffer and secondInputFrameBuffer pointers are the same, indicating to me that either the frameBufferCache provided me an already taken frameBuffer, or I missed some API change or usage change related to the new FrameBuffer cache system?

Related to this I also tried:

GPUImageVideoCamera -> GPUImageTwoInputFilter GPUImagePicture -> GPUImageFilter -> GPUImageTwoInputFilter

This gives the same error, however in this case the firstInputFrameBuffer and secondInputFrameBuffer pointers aren't the same. So there might be a deeper problem here?

schwarrrtz commented 9 years ago

I'm currently experiencing this as well, using 0.1.7. Is there a timeframe for implementing a fix? If someone can point me in the right direction I can take a crack at it.

gonghao commented 8 years ago

I met the same situations like #1551 under 0.1.7.

erickingxu commented 8 years ago

About overrelease problem, you can try codes as follows, it seems works to me: GPUImagePicture -> GPUImageFilterB -> GPUImageTwoInputFilter //set twoinputfilter atTextureLocation is 0; GPUImageVideoCamera -> GPUImageFilterA -> GPUImageTwoInputFilter //set twoinputfilter atTextureLocation is 1; and then start camera.... Maybe it should give some time for a image to be freshed into FBO with update method.

gonghao commented 8 years ago

@erickingxu I've tried the method you said, but failed.

GPUImagePicture -> GPUImageTransformFilter -> GPUImageNormalBlendFilter // atTextureLocation 1 GPUImageVideoCamera -> GPUImageCropFilter -> GPUImageNormalBlendFilter // atTextureLocation 0

scharli commented 8 years ago

Any update on this problem?

samuelbeek commented 8 years ago

@scharli you should checkout this: https://github.com/BradLarson/GPUImage/issues/1551. Hope it is of any help

scharli commented 8 years ago

After some memory warnings about my "solution" of comment [secondInputFrameBuffer unlock] of GPUImageTwoInputFilter.m i finally get #1551 approach width this code

imageBocaMask = [UIImage imageNamed:@"mask720.png"];
pictureBocaMask = [[GPUImagePicture alloc] initWithImage:imageBocaMask smoothlyScaleOutput:YES];

GPUImageOpacityFilter *opacityBocaFilter = [[GPUImageOpacityFilter alloc] init];
opacityBocaFilter.opacity = 0.0;

GPUImageNormalBlendFilter *preMaskBocaFilter = [[GPUImageNormalBlendFilter alloc] init];

[videoCamera addTarget:opacityBocaFilter];
[opacityBocaFilter addTarget:preMaskBocaFilter];
[pictureBocaMask addTarget:preMaskBocaFilter];`

Basically i mix video input with 0.0 alpha with the GPUImagePicture and i used the result for other processes

iPhonig commented 8 years ago

I've been experiencing this error as well, I tried adding a NormalBlend filter in however my output just became grey rather than displaying the actual video. My code is below. If anyone has any ideas that would be great. Thanks!

videoCamera = [[GPUImageVideoCamera alloc] initWithSessionPreset:AVCaptureSessionPreset1280x720 cameraPosition:AVCaptureDevicePositionFront]; filter = [[GPUImageFilter alloc] init];

[videoCamera addTarget:_filter]; blendFilter = [[GPUImageAlphaBlendFilter alloc] init]; blendFilter.mix = 1.0;

animatedImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)]; [contentView addSubview:_animatedImageView]; [contentView addSubview:[self watermark]]; uiElementInput = [[GPUImageUIElement alloc] initWithView:contentView];

[filter addTarget:blendFilter];

[uiElementInput addTarget:blendFilter];

[blendFilter addTarget:filteredVideoView];

filtered video view is GPUImageView

rued commented 8 years ago

Maybe you forgot to call Update on the GPUImageUIElement?

iPhonig commented 8 years ago

@rued I do when in a separate init method.

GPUImageUIElement *weakUIElementInput = _uiElementInput; [_filter setFrameProcessingCompletionBlock:^(GPUImageOutput * filter, CMTime frameTime){ [weakUIElementInput update]; }];

JoyLink commented 6 years ago

In my case:

- (void)unlock;
{
    if (referenceCountingDisabled)
    {
        return;
    }
    NSLog(@"%lul", (unsigned long)framebufferReferenceCount);
    NSAssert(framebufferReferenceCount > 0, @"Tried to overrelease a framebuffer, did you forget to call -useNextFrameForImageCapture before using -imageFromCurrentFramebuffer?");
    framebufferReferenceCount--;
    if (framebufferReferenceCount < 1)
    {
        [[GPUImageContext sharedFramebufferCache] returnFramebufferToCache:self];
    }
}

By printing the framebufferReferenceCount, I noticed that under some circumstance another thread will try to execute the "UNCLOCK" while the previous thread is still doing so. Before getting into the seamless solution, I would use this as a workaround:

if (referenceCountingDisabled || framebufferReferenceCount <= 0)
    {
        return;
    }