İki video arasında bir canlı renk filtresi uygulamak için GPUImage
ve AVVideoCompositing
kombinasyonunu kullanıyorum. CIImage
imageFromCVPixelBuffer
'u CGImage
GPUImage
'a CGImage
- CIImage
- CVPixelBuffer
no'lu numaralara dönüştürerek yapmak, oldukça verimsizdir ve bellek sorunlarına yol açar.AVVideoCompositing ile GPUImage'ı kullanma
GPUImage
Çerçevesinde doku nesneleri, işlem hedefleri ve çerçeve arabellekleri olduğunu fark ettim. Her şeyi GPU’da tutmak için iOS’ta CVOpenGLESTextureCacheCreateTextureFromImage
’u kullanabileceğini umuyordum.
Ben GPUImageTextureInput
nesne üzerinde bir filtre zinciri kurmak ve daha sonra filtre en renderTarget
, bir CVPixelBufferRef
olduğu alabilir varsayılır, çünkü oldukça çerçevenin iç işleyişini anlamak sanmıyorum. Aşağıdaki renderTarget
her zaman sıfırdır ve imageFromCurrentFrameBuffer
'u çağırmak bana gri bir kutu verecektir, bu benim resmim değil.
Aşağıdaki örnekte, kroma-anahtar değil, tek bir videoda basit bir parlaklık filtresi, kavramı denemek ve kanıtlamak içindir. Benim kompozisyon daha ayrıntılı denetim gerektiğinden
@implementation MyCustomCompositor : NSObject <AVVideoCompositing>
- (instancetype)init
{
self = [super init];
if (self) {
CVOpenGLESTextureCacheCreate(kCFAllocatorDefault, NULL, [GPUImageContext sharedImageProcessingContext].context, NULL, &_textureCache);
}
return self;
}
- (NSDictionary<NSString *,id> *)requiredPixelBufferAttributesForRenderContext
{
return @{(NSString *)kCVPixelBufferPixelFormatTypeKey : @[@(kCVPixelFormatType_32BGRA)],
(NSString *)kCVPixelBufferOpenGLCompatibilityKey : @YES};
}
- (NSDictionary<NSString *,id> *)sourcePixelBufferAttributes
{
return @{(NSString *)kCVPixelBufferPixelFormatTypeKey : @[@(kCVPixelFormatType_32BGRA)],
(NSString *)kCVPixelBufferOpenGLCompatibilityKey : @YES};
}
- (void)startVideoCompositionRequest:(AVAsynchronousVideoCompositionRequest *)asyncVideoCompositionRequest
{
@autoreleasepool {
CVPixelBufferRef mePixelBuffer = [asyncVideoCompositionRequest sourceFrameByTrackID:200];
CVPixelBufferLockBaseAddress(mePixelBuffer, kCVPixelBufferLock_ReadOnly);
CVOpenGLESTextureRef meTextureRef = NULL;
size_t width = CVPixelBufferGetWidth(mePixelBuffer);
size_t height = CVPixelBufferGetHeight(mePixelBuffer);
CVOpenGLESTextureCacheCreateTextureFromImage(kCFAllocatorDefault, _textureCache, mePixelBuffer, NULL, GL_TEXTURE_2D, GL_BGRA, (int)width, (int)height, GL_BGRA, GL_UNSIGNED_BYTE, 0, &meTextureRef);
GPUImageTextureInput *meTextureInput = [[GPUImageTextureInput alloc] initWithTexture:CVOpenGLESTextureGetName(meTextureRef) size:CGSizeMake(width, height)];
GPUImageBrightnessFilter *filter = [[GPUImageBrightnessFilter alloc] init];
filter.brightness = 0.5;
[meTextureInput addTarget:filter];
[filter setFrameProcessingCompletionBlock:^(GPUImageOutput *imageOutput, CMTime time) {
[asyncVideoCompositionRequest finishWithComposedVideoFrame:((GPUImageBrightnessFilter *)imageOutput).renderTarget];
}];
[meTextureInput processTextureWithFrameTime:kCMTimeZero];
CFRelease(meTextureRef);
CVOpenGLESTextureCacheFlush(_textureCache, 0);
CVPixelBufferUnlockBaseAddress(mePixelBuffer, kCVPixelBufferLock_ReadOnly);
}
}
ben GPUImage
içinde GPUMovieWriter
veya video API'leri kullanarak değilim. Kompozisyon, farklı zaman aralıklarında farklı bir yeşil video bindirmesine referans veren çok sayıda kroma-anahtar talimattan oluşabilir ve bana, GPUImage
'daki film API'lerinin bir video dosyasının tamamını filtrelemekle sınırlı olduğu görülüyor. Ayrıca, parçanın parçaları ve ses karışımlarını işlemek için yeteneklerine de ihtiyacım var.
Özel gölgelendiricilerle tüm bunları GL'de yapmak için kafamı sarmayı denedim, ancak yapmaya çalıştığım şeyi yapan mevcut çerçeveleri kullanacağımı düşündüm.
Bunu bir şans vereceğim! Teşekkürler! – dhenke
Bu konuda biraz kafam karıştı. Bu hemen hemen doğru GPUImageMovie, dışarı, kod gibi görünüyor, ama nasıl bir GPUImageOutput alt sınıfına uyarlamak için? CreateDataFBO çağrısı nasıl gerçekleşir? Yoksa bu alt sınıfı nasıl ayarlayacağım konusunda bazı parçalarımı mı kaçırıyorum? Ben createDataFBO çağırmak ve bir şey için bu ref atayarak sona ereceğini varsayalım? – dhenke
üzgünüm. Çıkışı vermeyi unuttum. : P, tamir edeyim. – econi