2015-06-30 14 views
8

Ich versuche, ein paar GPUImagePicture s als Textur-Quellen zusammen mit einem Fragment-Shader zum Filtern eines Video spielen.GPUImageMovie verwenden mehrere Bilder als Texturen und Prozess

Ich bin in der Lage, Standbilder auf diese Weise großartig zu verarbeiten, aber ich kann nicht herausfinden, was ich vermisse, um dies auf einer GPUImageMovie arbeiten zu lassen, würde ich jede Hilfe, die angeboten wird, schätzen.

@property (nonatomic, strong) GPUImageView *gpuPlayerView; 
@property (nonatomic, strong) GPUImageMovie *gpuMovie; 

AVPlayerItem *playerItem = [AVPlayerItem playerItemWithAsset:self.video]; 

self.player = [AVPlayer playerWithPlayerItem:playerItem]; 

self.player.actionAtItemEnd = AVPlayerActionAtItemEndNone; 

[self.player play]; 

self.gpuMovie = [[GPUImageMovie alloc]initWithPlayerItem:playerItem]; 

self.gpuMovie.playAtActualSpeed = YES; 

GPUImagePicture *sourcePicture1 = [[GPUImagePicture alloc]initWithImage: 
[UIImage imageNamed:@"FilterBG"]]; 

GPUImagePicture *sourcePicture2 = [[GPUImagePicture alloc]initWithImage: 
[UIImage imageNamed:@"FilterOverlay"]]; 

GPUImagePicture *sourcePicture3 = [[GPUImagePicture alloc]initWithImage: 
[UIImage imageNamed:@"Filter1Map"]]; 

GPUImageFilter *filter = [[GPUImageFourInputFilter alloc]initWithFragmentShaderFromString: 
kFilter1ShaderString]; 

[self.gpuMovie addTarget:filter atTextureLocation:0]; 

if (sourcePicture1) 
{ 
    [sourcePicture1 addTarget:filter atTextureLocation:1]; 
} 

if (sourcePicture2) 
{ 
    [sourcePicture2 addTarget:filter atTextureLocation:2]; 
} 

if (sourcePicture3) 
{ 
    [sourcePicture3 addTarget:filter atTextureLocation:3]; 
} 

[filter addTarget:self.gpuPlayerView]; 

[self.gpuMovie startProcessing]; 
+0

Bitte versuchen Sie, dies zu suchen, hilfreich sein .. [GPUImageMovie] (http://stackoverflow.com/questions/23799836/gpuimagemovie-pause -while-applying-filter) – 0yeoj

+0

Haben Sie ein minimales Projekt zur Veranschaulichung Ihres Problems? –

+0

Woher haben Sie Ihre Implementierung von GPUImageFourInputFilter? Angenommen, es basiert auf den GPUImageTwoInputFilter- oder GPUImageThreeInputFilter-Klassen, die mit dem Framework ausgeliefert werden.Möglicherweise möchten Sie diese Klasse einchecken, um sicherzustellen, dass Zeitstempeln für die Aktualisierung von Inhalten entsprechend weitergegeben werden. Testen Sie das obige mit einem GPUImageTwoInputFilter oder GPUImageThreeInputFilter und weniger Blend-Bildern, um zu sehen, ob dies in Ihrer GPUImageFourInputFilter-Implementierung lokalisiert ist. –

Antwort

-1

Es gibt eine Methode, die Ihnen die gleichen

CVOpenGLESTextureCacheCreateTextureFromImage

, die zwischen einer GL Textur und einem Film einen gemeinsamen Puffer erlaubt erreichen nutzen können. In diesem Core Video OpenGLES Texture Caches werden CVOpenGLESTextureRef Texturen zwischengespeichert und verwaltet. Diese Textur-Caches bieten Ihnen die Möglichkeit, Puffer mit verschiedenen Pixelformaten wie 420v oder BGRA direkt von GLES zu lesen und zu schreiben.

//Mapping a BGRA buffer as a source texture: 
CVOpenGLESTextureCacheCreateTextureFromImage(kCFAllocatorDefault, textureCache, pixelBuffer, NULL, GL_TEXTURE_2D, GL_RGBA, width, height, GL_RGBA, GL_UNSIGNED_BYTE, 0, &outTexture); 
//Mapping a BGRA buffer as a renderbuffer: 
CVOpenGLESTextureCacheCreateTextureFromImage(kCFAllocatorDefault, textureCache, pixelBuffer, NULL, GL_RENDERBUFFER, GL_RGBA8_OES, width, height, GL_RGBA, GL_UNSIGNED_BYTE, 0, &outTexture); 
//Mapping the luma plane of a 420v buffer as a source texture: 
CVOpenGLESTextureCacheCreateTextureFromImage(kCFAllocatorDefault, textureCache, pixelBuffer, NULL, GL_TEXTURE_2D, GL_LUMINANCE, width, height, GL_LUMINANCE, GL_UNSIGNED_BYTE, 0, &outTexture); 
//Mapping the chroma plane of a 420v buffer as a source texture: 
CVOpenGLESTextureCacheCreateTextureFromImage(kCFAllocatorDefault, textureCache, pixelBuffer, NULL, GL_TEXTURE_2D, GL_LUMINANCE_ALPHA, width/2, height/2, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, 1, &outTexture); 
//Mapping a yuvs buffer as a source texture (note: yuvs/f and 2vuy are unpacked and resampled -- not colorspace converted) 
CVOpenGLESTextureCacheCreateTextureFromImage(kCFAllocatorDefault, textureCache, pixelBuffer, NULL, GL_TEXTURE_2D, GL_RGB_422_APPLE, width, height, GL_RGB_422_APPLE, GL_UNSIGNED_SHORT_8_8_APPLE, 1, &outTexture); 

    CVReturn CVOpenGLESTextureCacheCreateTextureFromImage (CFAllocatorRef 
    __nullable allocator, CVOpenGLESTextureCacheRef __nonnull textureCache, CVImageBufferRef __nonnull sourceImage, CFDictionaryRef 
    __nullable textureAttributes, GLenum target, GLint internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, size_t planeIndex, CVOpenGLESTextureRef __nullable * __nonnull textureOut); 

Diese Funktion entweder erstellt eine neue oder wieder eine im Cache gespeicherte CVOpenGLESTextureRef Textur Objekt auf die CVImageBufferRef und die zugehörigen Parameter abgebildet. Diese Operation erstellt eine Live-Bindung zwischen dem Bildpuffer und dem zugrunde liegenden Texturobjekt.

Ich hoffe, dass Sie bei der Erstellung helfen, was erforderlich ist :)

+0

ist dieser Code ein CVPixelBufferRef und überlagern Sie ein Bild davon, während Sie die GPU nutzen. Entschuldigung, ich bin ein Anfänger bei OpenGLES. Und gibt die letzte Zeile einen CVPixelBufferRef zurück, der beide Bilder kombiniert hat? – Charlie

-2

Ich habe GPUImage ‚s Beispielcode (SimpleVideoFileFilter) versucht, die Ausgabe zu erreichen. Ich habe GPUImageFilterGroup erstellt und Filter hinzugefügt. Um Bilder als Textur hinzuzufügen, habe ich den Code GPUImageMissEtikateFilter Filter verwendet. Hier ist mein Code:

NSURL *sampleURL = [[NSBundle mainBundle] URLForResource:@"sample_iPod" withExtension:@"m4v"]; 

movieFile = [[GPUImageMovie alloc] initWithURL:sampleURL]; 
movieFile.runBenchmark = YES; 
movieFile.playAtActualSpeed = YES; 
// filter = [[GPUImageFilter alloc] initWithFragmentShaderFromFile:@"CustomFilter"]; 

filter = [[GPUImageFilterGroup alloc] init]; 

GPUImageSaturationFilter *saturationFilter = [[GPUImageSaturationFilter alloc] init]; 
[(GPUImageSaturationFilter *)saturationFilter setSaturation:0.0]; 
[(GPUImageFilterGroup *)filter addFilter:saturationFilter]; 

GPUImagePicture *lookupImageSource = [[GPUImagePicture alloc] initWithImage:[UIImage imageNamed:@"lookup_miss_etikate"]]; 
GPUImageLookupFilter *lookupFilter = [[GPUImageLookupFilter alloc] init]; 
[(GPUImageFilterGroup *)filter addFilter:lookupFilter]; 

[lookupImageSource addTarget:lookupFilter atTextureLocation:1]; 
[lookupImageSource processImage]; 

[saturationFilter addTarget:lookupFilter]; 

[(GPUImageFilterGroup *)filter setInitialFilters:@[saturationFilter]]; 
[(GPUImageFilterGroup *)filter setTerminalFilter:lookupFilter]; 

[movieFile addTarget:filter]; 

// Only rotate the video for display, leave orientation the same for recording 
GPUImageView *filterView = (GPUImageView *)self.view; 
[filter addTarget:filterView]; 

[movieFile startProcessing]; 

Ich hoffe, dies wird Ihnen helfen.

+0

Ich brauche einen Fragment-Shader und ich benutze 'GPUImagePictures' und nicht 'GPUImageLookupFilter's. – klcjr89

-2

Nach der Initialisierung des GPUImage:

GPUImagePicture *sourcePicture1 = [[GPUImagePicture alloc]initWithImage:[UIImage imageNamed:@"FilterBG"]]; 

Sie rufen müssen:

[sourcePicture1 processImage]; 

, um effektiv das Bild zu laden und sie die GPUImage Pipeline zur Verfügung zu stellen.

Und das gleiche für sourcePicture2 und sourcePicture3.

Update:

Was ich brauchte, vor ein paar Jahren zu tun, wenn ich es mit Filmen und Bildern verwenden, war eine Benachrichtigung hinzuzufügen, wenn der Film geladen wurde und bereit (in GPUImageMovie.m zu spielen, processAsset Verfahren , bevor self.decodeIsAllowed = YES;. Nur wenn der Film fertig war, legte ich sein GPUImage-Pipeline-Ziel fest.