私はGPUImage
とAVVideoCompositing
の組み合わせを使用して、2つのビデオ間にライブクロマキーフィルタを実装しようとしています。 CIImage
imageFromCVPixelBuffer
をCGImage
にGPUImage
を入力してCGImage
をCIImage
からCVPixelBuffer
に変更することは、非常に非効率的であり、メモリの問題を引き起こします。AVUIideoCompositingでGPUImageを使用する
GPUImage
フレームワークにテクスチャオブジェクト、レンダリングターゲット、およびフレームバッファがあることに気付きました。私は、iOSでCVOpenGLESTextureCacheCreateTextureFromImage
を活用して、GPU上のすべてを維持できることを期待していました。
私はGPUImageTextureInput
オブジェクトにフィルタチェーンを設定し、その後、CVPixelBufferRef
あるフィルタのrenderTarget
を得ることができると仮定ので、私は、私はかなりフレームワークの内部の仕組みを理解してるとは思いません。下のrenderTarget
は常にゼロです。imageFromCurrentFrameBuffer
を呼び出すと、私のイメージではない灰色のボックスが表示されます。
以下の例はクロマキーではなく、コンセプトを証明しようとする単一のビデオ上の簡単な輝度フィルタです。
@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);
}
}
私は私の構図をより細かく制御する必要があるので、私はGPUImage
でGPUMovieWriter
またはビデオAPIを使用していません。このコンポジションは、異なる時間範囲で異なる緑のビデオオーバーレイを参照する複数のクロマキー命令から構成できます。GPUImage
のムービーAPIは、ビデオファイル全体をフィルタリングすることに限定されています。トラックやオーディオミックスを操作するためのコンポジションの能力も必要です。
GLでカスタムシェイダーを使ってこのようなことをやり遂げようとしましたが、私がやろうとしていることをしているような既存のフレームワークを活用しようと考えました。
私はこれを撃つでしょう!ありがとう! – dhenke
私はこれで少し混乱しています。これはGPUImageMovieのコードのように見えますが、これはGPUImageOutputサブクラスにどのように適応させるのですか? createDataFBOの呼び出しはどのように行われますか?あるいは、私はこのサブクラスをどのように配置するかについていくつかの欠点がありますか?私はcreateDataFBOを呼び出して、そのrefを何かに割り当てることになると思いますか? – dhenke
申し訳ありません。私は出力を与えることを忘れた。 :P私はそれを修正させてください。 – econi