Skip to content

Commit

Permalink
Added iOS 5.0 texture cache support to GPUImageMovie, improving perfo…
Browse files Browse the repository at this point in the history
…rmance of movie playback.
  • Loading branch information
BradLarson committed Apr 3, 2012
1 parent a553d17 commit b1ca119
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 12 deletions.
Expand Up @@ -24,6 +24,7 @@ - (void)viewDidLoad
NSURL *sampleURL = [[NSBundle mainBundle] URLForResource:@"sample_iPod" withExtension:@"m4v"];

movieFile = [[GPUImageMovie alloc] initWithURL:sampleURL];
movieFile.runBenchmark = YES;
// filter = [[GPUImagePixellateFilter alloc] init];
filter = [[GPUImageAdaptiveThresholdFilter alloc] init];
GPUImageRotationFilter *rotationFilter = [[GPUImageRotationFilter alloc] initWithRotation:kGPUImageRotateRight];
Expand Down
6 changes: 5 additions & 1 deletion framework/Source/GPUImageMovie.h
Expand Up @@ -4,8 +4,12 @@
#import "GPUImageOutput.h"

@interface GPUImageMovie : GPUImageOutput
{
CVOpenGLESTextureCacheRef coreVideoTextureCache;
}

@property (readwrite, retain) NSURL *url;
@property(readwrite, retain) NSURL *url;
@property(readwrite, nonatomic) BOOL runBenchmark;

// Initialization and teardown
- (id)initWithURL:(NSURL *)url;
Expand Down
86 changes: 75 additions & 11 deletions framework/Source/GPUImageMovie.m
Expand Up @@ -3,6 +3,7 @@
@implementation GPUImageMovie

@synthesize url = _url;
@synthesize runBenchmark = _runBenchmark;

#pragma mark -
#pragma mark Initialization and teardown
Expand All @@ -14,6 +15,19 @@ - (id)initWithURL:(NSURL *)url;
return nil;
}

if ([GPUImageOpenGLESContext supportsFastTextureUpload])
{
[GPUImageOpenGLESContext useImageProcessingContext];
CVReturn err = CVOpenGLESTextureCacheCreate(kCFAllocatorDefault, NULL, (__bridge void *)[[GPUImageOpenGLESContext sharedImageProcessingOpenGLESContext] context], NULL, &coreVideoTextureCache);
if (err)
{
NSAssert(NO, @"Error at CVOpenGLESTextureCacheCreate %d");
}

// Need to remove the initially created texture
[self deleteOutputTexture];
}

self.url = url;

return self;
Expand Down Expand Up @@ -76,22 +90,72 @@ - (void)processMovieFrame:(CMSampleBufferRef)movieSampleBuffer;
CMTime currentSampleTime = CMSampleBufferGetOutputPresentationTimeStamp(movieSampleBuffer);
CVImageBufferRef movieFrame = CMSampleBufferGetImageBuffer(movieSampleBuffer);

// Upload to texture
CVPixelBufferLockBaseAddress(movieFrame, 0);
int bufferHeight = CVPixelBufferGetHeight(movieFrame);
int bufferWidth = CVPixelBufferGetWidth(movieFrame);

CFAbsoluteTime startTime = CFAbsoluteTimeGetCurrent();

if ([GPUImageOpenGLESContext supportsFastTextureUpload])
{
CVPixelBufferLockBaseAddress(movieFrame, 0);

[GPUImageOpenGLESContext useImageProcessingContext];
CVOpenGLESTextureRef texture = NULL;
CVReturn err = CVOpenGLESTextureCacheCreateTextureFromImage(kCFAllocatorDefault, coreVideoTextureCache, movieFrame, NULL, GL_TEXTURE_2D, GL_RGBA, bufferWidth, bufferHeight, GL_BGRA, GL_UNSIGNED_BYTE, 0, &texture);

if (!texture || err) {
NSLog(@"CVOpenGLESTextureCacheCreateTextureFromImage failed (error: %d)", err);
return;
}

outputTexture = CVOpenGLESTextureGetName(texture);
// glBindTexture(CVOpenGLESTextureGetTarget(texture), outputTexture);
glBindTexture(GL_TEXTURE_2D, outputTexture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

for (id<GPUImageInput> currentTarget in targets)
{
[currentTarget setInputSize:CGSizeMake(bufferWidth, bufferHeight)];

NSInteger indexOfObject = [targets indexOfObject:currentTarget];
[currentTarget setInputTexture:outputTexture atIndex:[[targetTextureIndices objectAtIndex:indexOfObject] integerValue]];

[currentTarget newFrameReadyAtTime:currentSampleTime];
}

CVPixelBufferUnlockBaseAddress(movieFrame, 0);

// Flush the CVOpenGLESTexture cache and release the texture
CVOpenGLESTextureCacheFlush(coreVideoTextureCache, 0);
CFRelease(texture);
outputTexture = 0;
}
else
{
// Upload to texture
CVPixelBufferLockBaseAddress(movieFrame, 0);

glBindTexture(GL_TEXTURE_2D, outputTexture);
// Using BGRA extension to pull in video frame data directly
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, bufferWidth, bufferHeight, 0, GL_BGRA, GL_UNSIGNED_BYTE, CVPixelBufferGetBaseAddress(movieFrame));

CGSize currentSize = CGSizeMake(bufferWidth, bufferHeight);
for (id<GPUImageInput> currentTarget in targets)
{
[currentTarget setInputSize:currentSize];
[currentTarget newFrameReadyAtTime:currentSampleTime];
}
CVPixelBufferUnlockBaseAddress(movieFrame, 0);
}

glBindTexture(GL_TEXTURE_2D, outputTexture);
// Using BGRA extension to pull in video frame data directly
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, bufferWidth, bufferHeight, 0, GL_BGRA, GL_UNSIGNED_BYTE, CVPixelBufferGetBaseAddress(movieFrame));

CGSize currentSize = CGSizeMake(bufferWidth, bufferHeight);
for (id<GPUImageInput> currentTarget in targets)
if (_runBenchmark)
{
[currentTarget setInputSize:currentSize];
[currentTarget newFrameReadyAtTime:currentSampleTime];
CFAbsoluteTime currentFrameTime = (CFAbsoluteTimeGetCurrent() - startTime);
NSLog(@"Current frame time : %f ms", 1000.0 * currentFrameTime);
}
CVPixelBufferUnlockBaseAddress(movieFrame, 0);
}

- (void)endProcessing;
Expand Down

0 comments on commit b1ca119

Please sign in to comment.