#import "GPUImageBuffer.h" @interface GPUImageBuffer() @end @implementation GPUImageBuffer @synthesize bufferSize = _bufferSize; #pragma mark - #pragma mark Initialization and teardown - (id)init; { if (!(self = [self initWithFragmentShaderFromString:kGPUImagePassthroughFragmentShaderString])) { return nil; } bufferedFramebuffers = [[NSMutableArray alloc] init]; // [bufferedTextures addObject:[NSNumber numberWithInt:outputTexture]]; _bufferSize = 1; return self; } - (void)dealloc { for (GPUImageFramebuffer *currentFramebuffer in bufferedFramebuffers) { [currentFramebuffer unlock]; } } #pragma mark - #pragma mark GPUImageInput - (void)newFrameReadyAtTime:(CMTime)frameTime atIndex:(NSInteger)textureIndex; { if ([bufferedFramebuffers count] >= _bufferSize) { outputFramebuffer = [bufferedFramebuffers objectAtIndex:0]; [bufferedFramebuffers removeObjectAtIndex:0]; } else { // Nothing yet in the buffer, so don't process further until the buffer is full outputFramebuffer = firstInputFramebuffer; [firstInputFramebuffer lock]; } [bufferedFramebuffers addObject:firstInputFramebuffer]; // Need to pass along rotation information, as we're just holding on to buffered framebuffers and not rotating them ourselves for (id currentTarget in targets) { if (currentTarget != self.targetToIgnoreForUpdates) { NSInteger indexOfObject = [targets indexOfObject:currentTarget]; NSInteger textureIndex = [[targetTextureIndices objectAtIndex:indexOfObject] integerValue]; [currentTarget setInputRotation:inputRotation atIndex:textureIndex]; } } // Let the downstream video elements see the previous frame from the buffer before rendering a new one into place [self informTargetsAboutNewFrameAtTime:frameTime]; // [self renderToTextureWithVertices:imageVertices textureCoordinates:[[self class] textureCoordinatesForRotation:inputRotation]]; } - (void)renderToTextureWithVertices:(const GLfloat *)vertices textureCoordinates:(const GLfloat *)textureCoordinates; { // No need to render to another texture anymore, since we'll be hanging on to the textures in our buffer } #pragma mark - #pragma mark Accessors - (void)setBufferSize:(NSUInteger)newValue; { if ( (newValue == _bufferSize) || (newValue < 1) ) { return; } if (newValue > _bufferSize) { NSUInteger texturesToAdd = newValue - _bufferSize; for (NSUInteger currentTextureIndex = 0; currentTextureIndex < texturesToAdd; currentTextureIndex++) { // TODO: Deal with the growth of the size of the buffer by rotating framebuffers, no textures } } else { NSUInteger texturesToRemove = _bufferSize - newValue; for (NSUInteger currentTextureIndex = 0; currentTextureIndex < texturesToRemove; currentTextureIndex++) { GPUImageFramebuffer *lastFramebuffer = [bufferedFramebuffers lastObject]; [bufferedFramebuffers removeObjectAtIndex:([bufferedFramebuffers count] - 1)]; [lastFramebuffer unlock]; lastFramebuffer = nil; } } _bufferSize = newValue; } @end