123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398 |
- #import "GPUImageOutput.h"
- #import "GPUImageMovieWriter.h"
- #import "GPUImagePicture.h"
- #import <mach/mach.h>
- void runOnMainQueueWithoutDeadlocking(void (^block)(void))
- {
- if ([NSThread isMainThread])
- {
- block();
- }
- else
- {
- dispatch_sync(dispatch_get_main_queue(), block);
- }
- }
- void runSynchronouslyOnVideoProcessingQueue(void (^block)(void))
- {
- dispatch_queue_t videoProcessingQueue = [GPUImageContext sharedContextQueue];
- #if (!defined(__IPHONE_6_0) || (__IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_6_0))
- if (dispatch_get_current_queue() == videoProcessingQueue)
- #else
- if (dispatch_get_specific([GPUImageContext contextKey]))
- #endif
- {
- block();
- }else
- {
- dispatch_sync(videoProcessingQueue, block);
- }
- }
- void runAsynchronouslyOnVideoProcessingQueue(void (^block)(void))
- {
- dispatch_queue_t videoProcessingQueue = [GPUImageContext sharedContextQueue];
-
- #if (!defined(__IPHONE_6_0) || (__IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_6_0))
- if (dispatch_get_current_queue() == videoProcessingQueue)
- #else
- if (dispatch_get_specific([GPUImageContext contextKey]))
- #endif
- {
- block();
- }else
- {
- dispatch_async(videoProcessingQueue, block);
- }
- }
- void runSynchronouslyOnContextQueue(GPUImageContext *context, void (^block)(void))
- {
- dispatch_queue_t videoProcessingQueue = [context contextQueue];
- #if (!defined(__IPHONE_6_0) || (__IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_6_0))
- if (dispatch_get_current_queue() == videoProcessingQueue)
- #else
- if (dispatch_get_specific([GPUImageContext contextKey]))
- #endif
- {
- block();
- }else
- {
- dispatch_sync(videoProcessingQueue, block);
- }
- }
- void runAsynchronouslyOnContextQueue(GPUImageContext *context, void (^block)(void))
- {
- dispatch_queue_t videoProcessingQueue = [context contextQueue];
-
- #if (!defined(__IPHONE_6_0) || (__IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_6_0))
- if (dispatch_get_current_queue() == videoProcessingQueue)
- #else
- if (dispatch_get_specific([GPUImageContext contextKey]))
- #endif
- {
- block();
- }else
- {
- dispatch_async(videoProcessingQueue, block);
- }
- }
- void reportAvailableMemoryForGPUImage(NSString *tag)
- {
- if (!tag)
- tag = @"Default";
-
- struct task_basic_info info;
-
- mach_msg_type_number_t size = sizeof(info);
-
- kern_return_t kerr = task_info(mach_task_self(),
-
- TASK_BASIC_INFO,
-
- (task_info_t)&info,
-
- &size);
- if( kerr == KERN_SUCCESS ) {
- NSLog(@"%@ - Memory used: %u", tag, (unsigned int)info.resident_size); //in bytes
- } else {
- NSLog(@"%@ - Error: %s", tag, mach_error_string(kerr));
- }
- }
- @implementation GPUImageOutput
- @synthesize shouldSmoothlyScaleOutput = _shouldSmoothlyScaleOutput;
- @synthesize shouldIgnoreUpdatesToThisTarget = _shouldIgnoreUpdatesToThisTarget;
- @synthesize audioEncodingTarget = _audioEncodingTarget;
- @synthesize targetToIgnoreForUpdates = _targetToIgnoreForUpdates;
- @synthesize frameProcessingCompletionBlock = _frameProcessingCompletionBlock;
- @synthesize enabled = _enabled;
- @synthesize outputTextureOptions = _outputTextureOptions;
- #pragma mark -
- #pragma mark Initialization and teardown
- - (id)init;
- {
- if (!(self = [super init]))
- {
- return nil;
- }
- targets = [[NSMutableArray alloc] init];
- targetTextureIndices = [[NSMutableArray alloc] init];
- _enabled = YES;
- allTargetsWantMonochromeData = YES;
- usingNextFrameForImageCapture = NO;
-
- // set default texture options
- _outputTextureOptions.minFilter = GL_LINEAR;
- _outputTextureOptions.magFilter = GL_LINEAR;
- _outputTextureOptions.wrapS = GL_CLAMP_TO_EDGE;
- _outputTextureOptions.wrapT = GL_CLAMP_TO_EDGE;
- _outputTextureOptions.internalFormat = GL_RGBA;
- _outputTextureOptions.format = GL_BGRA;
- _outputTextureOptions.type = GL_UNSIGNED_BYTE;
- return self;
- }
- - (void)dealloc
- {
- [self removeAllTargets];
- }
- #pragma mark -
- #pragma mark Managing targets
- - (void)setInputFramebufferForTarget:(id<GPUImageInput>)target atIndex:(NSInteger)inputTextureIndex;
- {
- [target setInputFramebuffer:[self framebufferForOutput] atIndex:inputTextureIndex];
- }
- - (GPUImageFramebuffer *)framebufferForOutput;
- {
- return outputFramebuffer;
- }
- - (void)removeOutputFramebuffer;
- {
- outputFramebuffer = nil;
- }
- - (void)notifyTargetsAboutNewOutputTexture;
- {
- for (id<GPUImageInput> currentTarget in targets)
- {
- NSInteger indexOfObject = [targets indexOfObject:currentTarget];
- NSInteger textureIndex = [[targetTextureIndices objectAtIndex:indexOfObject] integerValue];
-
- [self setInputFramebufferForTarget:currentTarget atIndex:textureIndex];
- }
- }
- - (NSArray*)targets;
- {
- return [NSArray arrayWithArray:targets];
- }
- - (void)addTarget:(id<GPUImageInput>)newTarget;
- {
- NSInteger nextAvailableTextureIndex = [newTarget nextAvailableTextureIndex];
- [self addTarget:newTarget atTextureLocation:nextAvailableTextureIndex];
-
- if ([newTarget shouldIgnoreUpdatesToThisTarget])
- {
- _targetToIgnoreForUpdates = newTarget;
- }
- }
- - (void)addTarget:(id<GPUImageInput>)newTarget atTextureLocation:(NSInteger)textureLocation;
- {
- if([targets containsObject:newTarget])
- {
- return;
- }
-
- cachedMaximumOutputSize = CGSizeZero;
- runSynchronouslyOnVideoProcessingQueue(^{
- [self setInputFramebufferForTarget:newTarget atIndex:textureLocation];
- [targets addObject:newTarget];
- [targetTextureIndices addObject:[NSNumber numberWithInteger:textureLocation]];
-
- allTargetsWantMonochromeData = allTargetsWantMonochromeData && [newTarget wantsMonochromeInput];
- });
- }
- - (void)removeTarget:(id<GPUImageInput>)targetToRemove;
- {
- if(![targets containsObject:targetToRemove])
- {
- return;
- }
-
- if (_targetToIgnoreForUpdates == targetToRemove)
- {
- _targetToIgnoreForUpdates = nil;
- }
-
- cachedMaximumOutputSize = CGSizeZero;
-
- NSInteger indexOfObject = [targets indexOfObject:targetToRemove];
- NSInteger textureIndexOfTarget = [[targetTextureIndices objectAtIndex:indexOfObject] integerValue];
- runSynchronouslyOnVideoProcessingQueue(^{
- [targetToRemove setInputSize:CGSizeZero atIndex:textureIndexOfTarget];
- [targetToRemove setInputRotation:kGPUImageNoRotation atIndex:textureIndexOfTarget];
- [targetTextureIndices removeObjectAtIndex:indexOfObject];
- [targets removeObject:targetToRemove];
- [targetToRemove endProcessing];
- });
- }
- - (void)removeAllTargets;
- {
- cachedMaximumOutputSize = CGSizeZero;
- runSynchronouslyOnVideoProcessingQueue(^{
- for (id<GPUImageInput> targetToRemove in targets)
- {
- NSInteger indexOfObject = [targets indexOfObject:targetToRemove];
- NSInteger textureIndexOfTarget = [[targetTextureIndices objectAtIndex:indexOfObject] integerValue];
-
- [targetToRemove setInputSize:CGSizeZero atIndex:textureIndexOfTarget];
- [targetToRemove setInputRotation:kGPUImageNoRotation atIndex:textureIndexOfTarget];
- }
- [targets removeAllObjects];
- [targetTextureIndices removeAllObjects];
-
- allTargetsWantMonochromeData = YES;
- });
- }
- #pragma mark -
- #pragma mark Manage the output texture
- - (void)forceProcessingAtSize:(CGSize)frameSize;
- {
-
- }
- - (void)forceProcessingAtSizeRespectingAspectRatio:(CGSize)frameSize;
- {
- }
- #pragma mark -
- #pragma mark Still image processing
- - (void)useNextFrameForImageCapture;
- {
- }
- - (CGImageRef)newCGImageFromCurrentlyProcessedOutput;
- {
- return nil;
- }
- - (CGImageRef)newCGImageByFilteringCGImage:(CGImageRef)imageToFilter;
- {
- GPUImagePicture *stillImageSource = [[GPUImagePicture alloc] initWithCGImage:imageToFilter];
-
- [self useNextFrameForImageCapture];
- [stillImageSource addTarget:(id<GPUImageInput>)self];
- [stillImageSource processImage];
-
- CGImageRef processedImage = [self newCGImageFromCurrentlyProcessedOutput];
-
- [stillImageSource removeTarget:(id<GPUImageInput>)self];
- return processedImage;
- }
- - (BOOL)providesMonochromeOutput;
- {
- return NO;
- }
- #pragma mark -
- #pragma mark Platform-specific image output methods
- #if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE
- - (UIImage *)imageFromCurrentFramebuffer;
- {
- UIDeviceOrientation deviceOrientation = [[UIDevice currentDevice] orientation];
- UIImageOrientation imageOrientation = UIImageOrientationLeft;
- switch (deviceOrientation)
- {
- case UIDeviceOrientationPortrait:
- imageOrientation = UIImageOrientationUp;
- break;
- case UIDeviceOrientationPortraitUpsideDown:
- imageOrientation = UIImageOrientationDown;
- break;
- case UIDeviceOrientationLandscapeLeft:
- imageOrientation = UIImageOrientationLeft;
- break;
- case UIDeviceOrientationLandscapeRight:
- imageOrientation = UIImageOrientationRight;
- break;
- default:
- imageOrientation = UIImageOrientationUp;
- break;
- }
-
- return [self imageFromCurrentFramebufferWithOrientation:imageOrientation];
- }
- - (UIImage *)imageFromCurrentFramebufferWithOrientation:(UIImageOrientation)imageOrientation;
- {
- CGImageRef cgImageFromBytes = [self newCGImageFromCurrentlyProcessedOutput];
- UIImage *finalImage = [UIImage imageWithCGImage:cgImageFromBytes scale:1.0 orientation:imageOrientation];
- CGImageRelease(cgImageFromBytes);
-
- return finalImage;
- }
- - (UIImage *)imageByFilteringImage:(UIImage *)imageToFilter;
- {
- CGImageRef image = [self newCGImageByFilteringCGImage:[imageToFilter CGImage]];
- UIImage *processedImage = [UIImage imageWithCGImage:image scale:[imageToFilter scale] orientation:[imageToFilter imageOrientation]];
- CGImageRelease(image);
- return processedImage;
- }
- - (CGImageRef)newCGImageByFilteringImage:(UIImage *)imageToFilter
- {
- return [self newCGImageByFilteringCGImage:[imageToFilter CGImage]];
- }
- #else
- - (NSImage *)imageFromCurrentFramebuffer;
- {
- return [self imageFromCurrentFramebufferWithOrientation:UIImageOrientationLeft];
- }
- - (NSImage *)imageFromCurrentFramebufferWithOrientation:(UIImageOrientation)imageOrientation;
- {
- CGImageRef cgImageFromBytes = [self newCGImageFromCurrentlyProcessedOutput];
- NSImage *finalImage = [[NSImage alloc] initWithCGImage:cgImageFromBytes size:NSZeroSize];
- CGImageRelease(cgImageFromBytes);
-
- return finalImage;
- }
- - (NSImage *)imageByFilteringImage:(NSImage *)imageToFilter;
- {
- CGImageRef image = [self newCGImageByFilteringCGImage:[imageToFilter CGImageForProposedRect:NULL context:[NSGraphicsContext currentContext] hints:nil]];
- NSImage *processedImage = [[NSImage alloc] initWithCGImage:image size:NSZeroSize];
- CGImageRelease(image);
- return processedImage;
- }
- - (CGImageRef)newCGImageByFilteringImage:(NSImage *)imageToFilter
- {
- return [self newCGImageByFilteringCGImage:[imageToFilter CGImageForProposedRect:NULL context:[NSGraphicsContext currentContext] hints:nil]];
- }
- #endif
- #pragma mark -
- #pragma mark Accessors
- - (void)setAudioEncodingTarget:(GPUImageMovieWriter *)newValue;
- {
- _audioEncodingTarget = newValue;
- if( ! _audioEncodingTarget.hasAudioTrack )
- {
- _audioEncodingTarget.hasAudioTrack = YES;
- }
- }
- @end
|