Search code examples
iosopengl-esgpuimage

Record OpenGL View with GPUImageMovieWriter


I'm trying to create an OpenGL view that will record with my app.

I'm trying to record the view with GPUImageMovieWriter and GPUImageUIElement

as such:

 self.imageUIElement = [[GPUImageUIElement alloc]initWithView:self.myView];

NSString *pathToMovie = [NSHomeDirectory() stringByAppendingPathComponent:@"Documents/Movie.m4v"];
unlink([pathToMovie UTF8String]); // If a file already exists, AVAssetWriter won't let you record new frames, so delete the old movie
NSURL *movieURL = [NSURL fileURLWithPath:pathToMovie];
movieWriter = [[GPUImageMovieWriter alloc] initWithMovieURL:movieURL size:CGSizeMake(480.0, 640.0)];

__weak UIViewController * controller = self;

movieWriter.completionBlock = ^{

    MPMoviePlayerViewController * _controller = [[MPMoviePlayerViewController alloc]initWithContentURL:movieURL];

    [controller presentMoviePlayerViewControllerAnimated:_controller];


};

[self.imageUIElement addTarget:movieWriter];

I have two buttons for stop an start the recording and when I stop the record I get the following error:

*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '*** -[AVAssetWriterInput markAsFinished] Cannot call method when status is 0'

?

My view is an OpenGL 1.x


Solution

  • You can't capture a view using OpenGL ES content with a GPUImageUIElement. This class uses the -renderInContext: method of CALayer to capture the contents of a layer (or UIView), but that method does not work with the CAEAGLLayers used for OpenGL ES.

    Instead, you're going to need to render your OpenGL ES view to a texture first, then pass that texture into a GPUImageTextureInput. You're going to need to make sure that your OpenGL ES context and the GPUImage context are in the same share group. I show an example of how to do this in the CubeExample sample application. GPUImage uses an OpenGL ES 2.0 context, but I believe you can use textures from a 1.1 context with it via a share group.

    You'd then feed this GPUImageTextureInput into your GPUImageMovieWriter. Make sure you provide appropriate timestamps for each rendered frame of your OpenGL ES scene, or the movie recording won't work quite right.