2015-06-30 24 views
8

Sto provando a utilizzare alcuni GPUImagePicture s come origini di trama insieme a uno shader di frammenti per filtrare un video in riproduzione.GPUImageMovie utilizza più immagini come trame e processi

Sono in grado di elaborare fermi immagine in questo modo, ma non riesco a capire cosa mi manca per farlo funzionare su un GPUImageMovie Apprezzerei qualsiasi aiuto offerto.

@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

Si prega di provare a guardare questo potrebbe essere utile .. [GPUImageMovie] (http://stackoverflow.com/questions/23799836/gpuimagemovie-pause -while-apply-filter) – 0yeoj

+0

Hai qualche progetto minimale da condividere per illustrare il tuo problema? –

+0

Dove hai ottenuto l'implementazione di GPUImageFourInputFilter? supponendo che fosse basato sulle classi GPUImageTwoInputFilter o GPUImageThreeInputFilter fornite con il framework.Potresti voler controllare in quella classe per assicurarti che stia propagando opportunamente la data e l'ora per l'aggiornamento del contenuto. Prova quanto sopra con un GPUImageTwoInputFilter o GPUImageThreeInputFilter e un minor numero di immagini miste per vedere se questo è localizzato sulla tua implementazione GPUImageFourInputFilter. –

risposta

-1

v'è un metodo che può essere utilizzato per ottenere lo stesso

CVOpenGLESTextureCacheCreateTextureFromImage

che permette un buffer condiviso tra una texture GL e un film. In questo Core Video, le cache di trama OpenGLES vengono utilizzate per memorizzare e gestire le trame CVOpenGLESTextureRef. Queste cache texture forniscono un modo per leggere e scrivere direttamente buffer con vari formati di pixel, come 420v o BGRA, da GLES.

//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); 

Questa funzione crea un nuovo o restituisce un oggetto CVOpenGLESTextureRef tessitura cache associata alla CVImageBufferRef e parametri associati. Questa operazione crea un binding live tra il buffer di immagini e l'oggetto texture sottostante.

Spero che vi aiuterà nella creazione di ciò che è necessario :)

+0

è questo codice che prende un CVPixelBufferRef e sovrappone un'immagine su di esso sfruttando al tempo stesso la GPU. Scusa, sono un principiante in OpenGLES. E poi l'ultima riga restituisce un CVPixelBufferRef che ha entrambe le immagini combinate? – Charlie

-2

Ho provato il codice di esempio GPUImage s’(SimpleVideoFileFilter) per ottenere l'output. Ho creato GPUImageFilterGroup e aggiungendo filtri ad esso. Per aggiungere immagini come texture, ho utilizzato il codice del filtro GPUImageMissEtikateFilter. Ecco il mio codice:

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]; 

Sperando che questo ti possa aiutare.

+0

Ho bisogno di usare un framment shader e sto usando 'GPUImagePicture's, e non' GPUImageLookupFilter's. – klcjr89

-2

Dopo l'inizializzazione del vostro GPUImage:

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

è necessario chiamare:

[sourcePicture1 processImage]; 

per caricare in modo efficace l'immagine e renderlo disponibile per la pipeline GPUImage.

E fare lo stesso per sourcePicture2 e sourcePicture3.

Aggiornamento:

Quello che mi serviva per fare un paio di anni fa, quando ho usato con filmati e immagini, è stato quello di aggiungere una notifica quando il film è stato caricato e pronto a giocare (in GPUImageMovie.m, processAsset metodo , prima del self.decodeIsAllowed = YES;. Solo quando il film era pronto, ho impostato il target della pipeline GPUImage.