@@ -0,0 +1,438 @@
#import " GPUImageFiveInputFilter.h"
static NSString *const kGPUImageFiveInputTextureVertexShaderString = SHADER_STRING
(
attribute vec4 position;
attribute vec4 inputTextureCoordinate;
attribute vec4 inputTextureCoordinate2;
attribute vec4 inputTextureCoordinate3;
attribute vec4 inputTextureCoordinate4;
attribute vec4 inputTextureCoordinate5;
varying vec2 textureCoordinate;
varying vec2 textureCoordinate2;
varying vec2 textureCoordinate3;
varying vec2 textureCoordinate4;
varying vec2 textureCoordinate5;
void main ()
{
gl_Position = position;
textureCoordinate = inputTextureCoordinate.xy ;
textureCoordinate2 = inputTextureCoordinate2.xy ;
textureCoordinate3 = inputTextureCoordinate3.xy ;
textureCoordinate4 = inputTextureCoordinate4.xy ;
textureCoordinate5 = inputTextureCoordinate5.xy ;
}
);
@implementation GPUImageFiveInputFilter
#pragma mark -
#pragma mark Initialization and teardown
- (id )initWithFragmentShaderFromString : (NSString *)fragmentShaderString ;
{
if (!(self = [self initWithVertexShaderFromString: kGPUImageFiveInputTextureVertexShaderString fragmentShaderFromString: fragmentShaderString]))
{
return nil ;
}
return self;
}
- (id )initWithVertexShaderFromString : (NSString *)vertexShaderString fragmentShaderFromString : (NSString *)fragmentShaderString ;
{
if (!(self = [super initWithVertexShaderFromString: vertexShaderString fragmentShaderFromString: fragmentShaderString]))
{
return nil ;
}
inputRotation5 = kGPUImageNoRotation ;
hasSetFourthTexture = NO ;
hasReceivedFifthFrame = NO ;
fifthFrameWasVideo = NO ;
fifthFrameCheckDisabled = NO ;
fifthFrameTime = kCMTimeInvalid ;
runSynchronouslyOnVideoProcessingQueue (^{
[GPUImageContext useImageProcessingContext ];
filterFifthTextureCoordinateAttribute = [filterProgram attributeIndex: @" inputTextureCoordinate5" ];
filterInputTextureUniform4 = [filterProgram uniformIndex: @" inputImageTexture5" ]; // This does assume a name of "inputImageTexture5" for the fifth input texture in the fragment shader
glEnableVertexAttribArray (filterFifthTextureCoordinateAttribute);
});
return self;
}
- (void )initializeAttributes ;
{
[super initializeAttributes ];
[filterProgram addAttribute: @" inputTextureCoordinate5" ];
}
- (void ) disableFifthFrameCheck
{
fourthFrameCheckDisabled = YES ;
}
#pragma mark -
#pragma mark Rendering
- (void )renderToTextureWithVertices : (const GLfloat *)vertices textureCoordinates : (const GLfloat *)textureCoordinates ;
{
if (self.preventRendering )
{
[firstInputFramebuffer unlock ];
[secondInputFramebuffer unlock ];
[thirdInputFramebuffer unlock ];
[fourthInputFramebuffer unlock ];
[fifthInputFramebuffer unlock ];
return ;
}
[GPUImageContext setActiveShaderProgram: filterProgram];
outputFramebuffer = [[GPUImageContext sharedFramebufferCache ] fetchFramebufferForSize: [self sizeOfFBO ] textureOptions: self .outputTextureOptions onlyTexture: NO ];
[outputFramebuffer activateFramebuffer ];
if (usingNextFrameForImageCapture)
{
[outputFramebuffer lock ];
}
[self setUniformsForProgramAtIndex: 0 ];
glClearColor (backgroundColorRed, backgroundColorGreen, backgroundColorBlue, backgroundColorAlpha);
glClear (GL_COLOR_BUFFER_BIT);
glActiveTexture (GL_TEXTURE2);
glBindTexture (GL_TEXTURE_2D, [firstInputFramebuffer texture ]);
glUniform1i (filterInputTextureUniform, 2 );
glActiveTexture (GL_TEXTURE3);
glBindTexture (GL_TEXTURE_2D, [secondInputFramebuffer texture ]);
glUniform1i (filterInputTextureUniform2, 3 );
glActiveTexture (GL_TEXTURE4);
glBindTexture (GL_TEXTURE_2D, [thirdInputFramebuffer texture ]);
glUniform1i (filterInputTextureUniform3, 4 );
glActiveTexture (GL_TEXTURE5);
glBindTexture (GL_TEXTURE_2D, [fourthInputFramebuffer texture ]);
glUniform1i (filterInputTextureUniform4, 5 );
glActiveTexture (GL_TEXTURE6);
glBindTexture (GL_TEXTURE_2D, [fifthInputFramebuffer texture ]);
glUniform1i (filterInputTextureUniform5, 6 );
glVertexAttribPointer (filterPositionAttribute, 2 , GL_FLOAT, 0 , 0 , vertices);
glVertexAttribPointer (filterTextureCoordinateAttribute, 2 , GL_FLOAT, 0 , 0 , textureCoordinates);
glVertexAttribPointer (filterSecondTextureCoordinateAttribute, 2 , GL_FLOAT, 0 , 0 , [[self class ] textureCoordinatesForRotation: inputRotation2]);
glVertexAttribPointer (filterThirdTextureCoordinateAttribute, 2 , GL_FLOAT, 0 , 0 , [[self class ] textureCoordinatesForRotation: inputRotation3]);
glVertexAttribPointer (filterFourthTextureCoordinateAttribute, 2 , GL_FLOAT, 0 , 0 , [[self class ] textureCoordinatesForRotation: inputRotation4]);
glVertexAttribPointer (filterFourthTextureCoordinateAttribute, 2 , GL_FLOAT, 0 , 0 , [[self class ] textureCoordinatesForRotation: inputRotation5]);
glDrawArrays (GL_TRIANGLE_STRIP, 0 , 4 );
[firstInputFramebuffer unlock ];
[secondInputFramebuffer unlock ];
[thirdInputFramebuffer unlock ];
[fourthInputFramebuffer unlock ];
[fifthInputFramebuffer unlock ];
if (usingNextFrameForImageCapture)
{
dispatch_semaphore_signal (imageCaptureSemaphore);
}
}
#pragma mark -
#pragma mark GPUImageInput
- (NSInteger )nextAvailableTextureIndex ;
{
if (hasSetFourthTexture){
return 4 ;
}
else if (hasSetThirdTexture){
return 3 ;
}
else if (hasSetSecondTexture)
{
return 2 ;
}
else if (hasSetFirstTexture)
{
return 1 ;
}
else
{
return 0 ;
}
}
- (void )setInputFramebuffer : (GPUImageFramebuffer *)newInputFramebuffer atIndex : (NSInteger )textureIndex ;
{
if (textureIndex == 0 )
{
firstInputFramebuffer = newInputFramebuffer;
hasSetFirstTexture = YES ;
[firstInputFramebuffer lock ];
}
else if (textureIndex == 1 )
{
secondInputFramebuffer = newInputFramebuffer;
// hasSetSecondTexture = YES;
[secondInputFramebuffer lock ];
}
else if (textureIndex == 2 ){
thirdInputFramebuffer = newInputFramebuffer;
[thirdInputFramebuffer lock ];
}
else if (textureIndex == 3 )
{
fourthInputFramebuffer = newInputFramebuffer;
[fourthInputFramebuffer lock ];
}
else if (textureIndex == 4 )
{
fifthInputFramebuffer = newInputFramebuffer;
[fifthInputFramebuffer lock ];
}
}
- (void )setInputSize : (CGSize)newSize atIndex : (NSInteger )textureIndex ;
{
if (textureIndex == 0 )
{
[super setInputSize: newSize atIndex: textureIndex];
if (CGSizeEqualToSize (newSize, CGSizeZero))
{
hasSetFirstTexture = NO ;
}
}
else if (textureIndex == 1 )
{
if (CGSizeEqualToSize (newSize, CGSizeZero))
{
hasSetSecondTexture = NO ;
}
}
else if (textureIndex == 2 )
{
if (CGSizeEqualToSize (newSize, CGSizeZero)) {
hasSetThirdTexture = NO ;
}
}
else if (textureIndex == 3 )
{
if (CGSizeEqualToSize (newSize, CGSizeZero)) {
hasSetFourthTexture = NO ;
}
}
}
- (void )setInputRotation : (GPUImageRotationMode)newInputRotation atIndex : (NSInteger )textureIndex ;
{
if (textureIndex == 0 )
{
inputRotation = newInputRotation;
}
else if (textureIndex == 1 )
{
inputRotation2 = newInputRotation;
}
else if (textureIndex == 2 )
{
inputRotation3 = newInputRotation;
}
else if (textureIndex == 3 )
{
inputRotation4 = newInputRotation;
}
else
{
inputRotation5 = newInputRotation;
}
}
- (CGSize)rotatedSize : (CGSize)sizeToRotate forIndex : (NSInteger )textureIndex ;
{
CGSize rotatedSize = sizeToRotate;
GPUImageRotationMode rotationToCheck;
if (textureIndex == 0 )
{
rotationToCheck = inputRotation;
}
else if (textureIndex == 1 )
{
rotationToCheck = inputRotation2;
}
else if (textureIndex == 2 )
{
rotationToCheck = inputRotation3;
}
else if (textureIndex == 3 )
{
rotationToCheck = inputRotation4;
}
else
{
rotationToCheck = inputRotation5;
}
if (GPUImageRotationSwapsWidthAndHeight (rotationToCheck))
{
rotatedSize.width = sizeToRotate.height ;
rotatedSize.height = sizeToRotate.width ;
}
return rotatedSize;
}
- (void )newFrameReadyAtTime : (CMTime)frameTime atIndex : (NSInteger )textureIndex ;
{
// You can set up infinite update loops, so this helps to short circuit them
if (hasReceivedFirstFrame && hasReceivedSecondFrame && hasReceivedThirdFrame && hasReceivedFourthFrame && hasReceivedFifthFrame)
{
return ;
}
BOOL updatedMovieFrameOppositeStillImage = NO ;
if (textureIndex == 0 )
{
hasReceivedFirstFrame = YES ;
firstFrameTime = frameTime;
if (secondFrameCheckDisabled)
{
hasReceivedSecondFrame = YES ;
}
if (thirdFrameCheckDisabled)
{
hasReceivedThirdFrame = YES ;
}
if (fourthFrameCheckDisabled) {
hasReceivedFourthFrame = YES ;
}
if (fifthFrameCheckDisabled) {
hasReceivedFifthFrame = YES ;
}
if (!CMTIME_IS_INDEFINITE (frameTime))
{
if CMTIME_IS_INDEFINITE (secondFrameTime)
{
updatedMovieFrameOppositeStillImage = YES ;
}
}
}
else if (textureIndex == 1 )
{
hasReceivedSecondFrame = YES ;
secondFrameTime = frameTime;
if (firstFrameCheckDisabled)
{
hasReceivedFirstFrame = YES ;
}
if (thirdFrameCheckDisabled)
{
hasReceivedThirdFrame = YES ;
}
if (fourthFrameCheckDisabled) {
hasReceivedFourthFrame = YES ;
}
if (fifthFrameCheckDisabled) {
hasReceivedFifthFrame = YES ;
}
if (!CMTIME_IS_INDEFINITE (frameTime))
{
if CMTIME_IS_INDEFINITE (firstFrameTime)
{
updatedMovieFrameOppositeStillImage = YES ;
}
}
}
else if (textureIndex == 2 )
{
hasReceivedThirdFrame = YES ;
thirdFrameTime = frameTime;
if (firstFrameCheckDisabled)
{
hasReceivedFirstFrame = YES ;
}
if (secondFrameCheckDisabled)
{
hasReceivedSecondFrame = YES ;
}
if (fourthFrameCheckDisabled) {
hasReceivedFourthFrame = YES ;
}
if (fifthFrameCheckDisabled) {
hasReceivedFifthFrame = YES ;
}
if (!CMTIME_IS_INDEFINITE (frameTime))
{
if CMTIME_IS_INDEFINITE (firstFrameTime)
{
updatedMovieFrameOppositeStillImage = YES ;
}
}
}else
{
hasReceivedFourthFrame = YES ;
fourthFrameTime = frameTime;
if (firstFrameCheckDisabled) {
hasReceivedFirstFrame = YES ;
}
if (secondFrameCheckDisabled) {
hasReceivedSecondFrame = YES ;
}
if (thirdFrameCheckDisabled) {
hasReceivedThirdFrame = YES ;
}
if (fifthFrameCheckDisabled) {
hasReceivedFifthFrame = YES ;
}
if (!CMTIME_IS_INDEFINITE (frameTime))
{
if CMTIME_IS_INDEFINITE (firstFrameTime)
{
updatedMovieFrameOppositeStillImage = YES ;
}
}
}
if ((hasReceivedFirstFrame && hasReceivedSecondFrame && hasReceivedThirdFrame && hasReceivedFourthFrame && hasReceivedFifthFrame) || updatedMovieFrameOppositeStillImage)
{
static const GLfloat imageVertices[] = {
-1 .0f , -1 .0f ,
1 .0f , -1 .0f ,
-1 .0f , 1 .0f ,
1 .0f , 1 .0f ,
};
[self renderToTextureWithVertices: imageVertices textureCoordinates: [[self class ] textureCoordinatesForRotation: inputRotation]];
[self informTargetsAboutNewFrameAtTime: frameTime];
hasReceivedFirstFrame = NO ;
hasReceivedSecondFrame = NO ;
hasReceivedThirdFrame = NO ;
hasReceivedFourthFrame = NO ;
hasReceivedFifthFrame = NO ;
}
}
@end