GPUImageMovieWriter crashes on assetWriterPixelBufferInput - ios

UPDATE: I know now that i'm sending messages to a deallocated instance, i think i've setup my project correct, but are starting to doubt this....
I've read brad's documentation and set up my project as no-arc, that will probably have something to do with the situation. I've added the linker flag -fobjc-arc and targeted GPUImage and my target to ios 4.3.
Any one out there with the same problem that discoverd what he/she was doing wrong????
I've been searching for an answer for days now, but I can't fix it and have run out of ideas.
Whenever I try to record a movie with the GPUImageMovieWriter my app crashes (EXC_BADACCESS) on:
CVPixelBufferPoolCreatePixelBuffer (NULL, [assetWriterPixelBufferInput pixelBufferPool], &renderTarget);
Full code:
NSString *pathToMovie = [NSHomeDirectory() stringByAppendingPathComponent:#"Documents/file.mov"];
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];
GPUImageSepiaFilter *sepiaFilter = [[GPUImageSepiaFilter alloc] init];
[videoCamera addTarget:sepiaFilter];
movieWriter = [[GPUImageMovieWriter alloc] initWithMovieURL:movieURL size:CGSizeMake(640.0, 480.0)];
movieWriter.encodingLiveVideo = YES;
[sepiaFilter addTarget:movieWriter];
movieWriter.shouldPassthroughAudio = YES;
videoCamera.audioEncodingTarget = movieWriter;
[movieWriter startRecording];
Ant help or pointers welcome!

Related

ios - How to properly export videos using GPUImage

I can't seem to get the GPUImageMovieWriter to work properly.
Despite the fact that the authors are always suggesting to look over their examples; none of them are able to properly build and run.
So here's my code sample:
ALAsset *asset = (ALAsset *)[self galleryImages][indexPath.row];
NSURL *fileURLForInput = [asset valueForProperty:ALAssetPropertyAssetURL];
GPUImageMovie *movieFile = [[GPUImageMovie alloc] initWithURL:fileURLForInput];
movieFile.runBenchmark = YES;
movieFile.playAtActualSpeed = NO;
NSURL *fileURLForOutput = [NSURL fileURLWithPath:[self getVideoLocalFilePathWithVideoID:videoID]];
GPUImageMovieWriter *movieWriter = [[GPUImageMovieWriter alloc] initWithMovieURL:fileURLForOutput size:CGSizeMake(640, 480)];
movieWriter.shouldPassthroughAudio = YES;
movieFile.audioEncodingTarget = movieWriter;
[movieFile enableSynchronizedEncodingUsingMovieWriter:movieWriter];
[movieWriter startRecording];
[movieFile startProcessing];
[movieWriter setCompletionBlock:^{
PSLog(#"DONE!");
}];
Running the code sample results in a "EXC_BAD_ACCESS" error.
And if I were to remove this line:
[movieFile enableSynchronizedEncodingUsingMovieWriter:movieWriter];
The app does not crash but the output file has a size of 0 bytes and the completion block is never called.
Any ideas? :(
You need to call [movieFile addTarget:movieWriter] before you start processing the movie.
I think you need to make the GPUImageMovie and GPUImageMovieWriter variable a strong property or an instance variable.

How to save a movie using GPUImage framework?

I am trying to process a video by adding a filter between GPUImageMovie and GPUImageMovieWriter. However, I got a trouble before adding a custom filter.
Here is my testing code.
NSURL *sampleURL = [[NSBundle mainBundle] URLForResource:#"Documents/test" withExtension:#"mov"];
movieFile = [[GPUImageMovie alloc] initWithURL:sampleURL];
NSString *pathToMovie = [NSHomeDirectory() stringByAppendingPathComponent:#"Documents/output.mov"];
unlink([pathToMovie UTF8String]);
NSURL *movieURL = [NSURL fileURLWithPath:pathToMovie];
movieWriter = [[GPUImageMovieWriter alloc] initWithMovieURL:movieURL size:CGSizeMake(1280.0, 720.0)];
[movieFile addTarget:movieWriter];
[movieWriter startRecording];
[movieFile startProcessing];
[movieWriter setCompletionBlock:^{
[movieFile removeTarget:movieWriter];
[movieWriter finishRecording];
}];
I got a error message like this
uncaught exception 'NSInvalidArgumentException', reason: '*** -[AVAssetReader initWithAsset:error:] invalid parameter not satisfying: asset != ((void*)0)'
, and there is a file named output.mov created under Documents folder with size 0.
What can I do to fix this simple task?
Your problem appears to be here:
[pixellateFilter addTarget:movieWriter];
[movieFile addTarget:movieWriter];
You're adding both the filter and movie source to the movie writer. I think what you mean to do is this:
[movieFile addTarget:pixellateFilter];
[pixellateFilter addTarget:movieWriter];
This error means that the sample file is not found or it's size is zero.
I believe you are mixing up the bundle files with the sandbox files. Where is your test.mov file? If it is in the bundle (i.e. added to the project files) then you should use:
NSURL *sampleURL = [[NSBundle mainBundle] URLForResource:#"test" withExtension:#"mov"];
Even if it is under a folder named Documents.
But if it is in the sandbox files of the app, then you should use:
NSString *pathToSample = [NSHomeDirectory() stringByAppendingPathComponent:#"Documents/test.mov"];
NSURL *sampleURL = [NSURL fileURLWithPath:pathToSample];

Blend two videos with chroma key using GPUImage

I try to blend two videos using GPUImage. One of them (show.mov) contain green background.
Here is show.mov and galaxy.mov.
I downloaded the latest version of GPUImage and changed SimpleVideoFileFilter example:
- (void)viewDidLoad
{
[super viewDidLoad];
_movie = [[GPUImageMovie alloc] initWithURL:[NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:#"galaxy" ofType:#"mov"]]];
_greenMovie = [[GPUImageMovie alloc] initWithURL:[NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:#"snow" ofType:#"mov"]]];
_movie.playAtActualSpeed = YES;
_greenMovie.playAtActualSpeed = YES;
_filter = [[GPUImageChromaKeyBlendFilter alloc] init];
[_greenMovie addTarget:_filter];
[_movie addTarget:_filter];
GPUImageView *filterView = (GPUImageView *)self.view;
[_filter addTarget:filterView];
[_greenMovie startProcessing];
[_movie startProcessing];
}
When I run the project (no matter on device or simulator) I get just blank white view and after 14 seconds (length of show.mov) I see only last frame of blended videos. Using writer from example create file on disk, but this file can't be opened.
I am using iPhone 5 with 7.0.3 and XCode 5.0.2
Did I miss something?
Thanks to #BradLarson, he pointed to an github issue where I found commit that caused this problem.
In GPUImageMovie.m I comment two lines in startProcessing method:
[inputAsset loadValuesAsynchronouslyForKeys:[NSArray arrayWithObject:#"tracks"] completionHandler: ^{
//runSynchronouslyOnVideoProcessingQueue(^{
NSError *error = nil;
AVKeyValueStatus tracksStatus = [inputAsset statusOfValueForKey:#"tracks" error:&error];
if (!tracksStatus == AVKeyValueStatusLoaded)
{
return;
}
blockSelf.asset = inputAsset;
[blockSelf processAsset];
blockSelf = nil;
//});
}];

I'm trying to get the video filtering working

I've tried the examples from the GPUImage library.
I tried the 'SimpleVideoFileFilter' but all I see its black screen with the slider.
I tried to do the same by my self, I got the images working perfect.
but I can't really understand the videos process.
the examples taking the videos from the project itself ? folder from the mac ? or its from the iPhone's videos ?
I don't have Apple Developer account, so I can't really test it on my device.
I found way to put an random (.m4v) file in the iPhone Simulator, and tried to play/filter the video.
anyone had this issue ? I'm trying for now just to play the video from the iPhone Simulator or the resource files .. I don't really know where how its works.
I tried this link, no luck.
Here is part of the example that we can find in GPUImage:
- (void)viewDidLoad
{
[super viewDidLoad];
NSURL *sampleURL = [[NSBundle mainBundle] URLForResource:#"sample_iPod" withExtension:#"m4v"];
movieFile = [[GPUImageMovie alloc] initWithURL:sampleURL];
movieFile.runBenchmark = YES;
movieFile.playAtActualSpeed = YES;
filter = [[GPUImagePixellateFilter alloc] init];
// filter = [[GPUImageUnsharpMaskFilter alloc] init];
[movieFile addTarget:filter];
// Only rotate the video for display, leave orientation the same for recording
GPUImageView *filterView = (GPUImageView *)self.view;
[filter addTarget:filterView];
// In addition to displaying to the screen, write out a processed version of the movie to disk
NSString *pathToMovie = [NSHomeDirectory() stringByAppendingPathComponent:#"Documents/TestMovie.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(640.0, 480.0)];
[filter addTarget:movieWriter];
// Configure this for video from the movie file, where we want to preserve all video frames and audio samples
movieWriter.shouldPassthroughAudio = YES;
movieFile.audioEncodingTarget = movieWriter;
[movieFile enableSynchronizedEncodingUsingMovieWriter:movieWriter];
[movieWriter startRecording];
[movieFile startProcessing];
[movieWriter setCompletionBlock:^{
[filter removeTarget:movieWriter];
[movieWriter finishRecording];
}];
}
simple code that should filter the video ..
all I get from there is black screen with the slider ..
I'm talking about this project.
Movie playback does not currently work within the Simulator using GPUImage. You'll need to run this on an actual device to have this work.
I'm not sure why movie files don't output anything when run from the Simulator, but you're welcome to dig into the GPUImageMovie code and see what might be wrong. Since it runs fine when operated on actual hardware, it hasn't been a priority of mine to fix.

GPUImage + Get Blank Video as output of video file overlay

I am using GPUImage framework and it is so good. In my app, i have record video and then add overlay on recorder video. (due to my requirement.)
Step 1: recording video is working fine and i am getting correct video.
Step 2: Add overlay on video file, here i am getting issue and get black video as output with small size.
My code is as below:
self.movieFile = [[GPUImageMovie alloc] initWithURL:capturevideoURL];
self.movieFile.delegate = self;
self.movieFile.runBenchmark = YES;
self.movieFile.playAtActualSpeed = YES;
[self.movieFile addTarget:self.filter];
UIImage *inputImage = self.overlayImage;
GPUImagePicture *overlayPicture = [[GPUImagePicture alloc] initWithImage:inputImage];
[overlayPicture addTarget:self.filter];
[overlayPicture processImage];
// Only rotate the video for display, leave orientation the same for recording
GPUImageView *filterView = (GPUImageView *)self.view;
[self.filter addTarget:filterView];
[CommonFunction DeleteFileFromApp:#"Movie.m4v"];
NSString *pathToMovie = [CommonFunction GetPathForFileName:#"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];
self.movieWriter = [[GPUImageMovieWriter alloc] initWithMovieURL:movieURL size:CGSizeMake(320.0, 480.0)];
[self.filter addTarget:self.movieWriter];
// Configure this for video from the movie file, where we want to preserve all video frames and audio samples
self.movieWriter.shouldPassthroughAudio = YES;
self.movieFile.audioEncodingTarget = self.movieWriter;
[self.movieFile enableSynchronizedEncodingUsingMovieWriter:self.movieWriter];
[self.movieWriter startRecording];
[self.movieFile startProcessing];
NSLog(#"Start Overlaying...");
__weak GPUImageNormalBlendFilter *filterlocal = self.filter;
__weak GPUImageMovieWriter *moviewriterlocal = self.movieWriter;
__weak typeof(self) weakSelf = self;
[movieWriter setCompletionBlock:^{
[filterlocal removeTarget:moviewriterlocal];
[moviewriterlocal finishRecording];
[weakSelf loadVideo];
}];
Can you suggest me, how to solve this issue of black video output?
Thanks

Resources