3

I am having an issue running GPUImage. I have modified SimpleVideoFileFilter program(replaced the filter with a chromakeyfilter) and am using my own video. My program is terminating due to the following error:

[AVAssetWriter startWriting] Cannot call method when status is 3'

I have gone through the forums but not sure why the moviewriter is closing and then someone is writing to it.

I am using iPhone4 running iOS 7.0

Any clues are greatly appreciated. Thanks much!

user2869423
  • 31
  • 2
  • 3
  • AVAssetWriterStatusFailed is the status implied by '3' [here's the relevant place in Apple's Docs](https://developer.apple.com/library/ios/documentation/AVFoundation/Reference/AVAssetWriter_Class/Reference/Reference.html#//apple_ref/doc/c_ref/AVAssetWriterStatus) There are many possible reasons for this, but you'll have to post your code so we can make informed suggestions. Could you please post how you setup the filter, and how you get the NSURL for your video? – ryan cumley Oct 15 '13 at 18:37
  • Please find the code to setup filter and NSURL for the video. Thanks – user2869423 Oct 24 '13 at 21:49
  • I met it last night,and I resolve it by correct the url,so check the url – aKerdi Jan 01 '17 at 08:06
  • @aKerdi Can you please describe how you solved it? – Seasia Creative Crew Jan 11 '17 at 06:58

6 Answers6

6

Check whether your destination file exists already. If it does, remove it.

Hermann Döppes
  • 1,373
  • 1
  • 18
  • 26
Darktt
  • 184
  • 2
  • 7
1

I was trying to add the file to a directory which did not exist. Example : /Videos/Video.mov , leaving it just /Video.mov worked.

Sam Bing
  • 2,794
  • 1
  • 19
  • 29
0
movieFile1 = [[GPUImageMovie alloc] initWithURL:movieFileURL1];

movieFile2 = [[GPUImageMovie alloc] initWithURL:movieFileURL2];
movieFile2.runBenchmark = YES;
movieFile2.playAtActualSpeed = NO;

filter = [[GPUImageChromaKeyBlendFilter alloc] init];
[(GPUImageChromaKeyBlendFilter *)filter setColorToReplaceRed:0.0 green:1.0 blue:0.0];
[(GPUImageChromaKeyBlendFilter *)filter setThresholdSensitivity:0.4];

GPUImageView *filterView = (GPUImageView*)displayView;
[filter addTarget:displayView];

[movieFile1 addTarget:filter];
[movieFile2 addTarget:filter];

NSString *pathToMovie = [NSHomeDirectory() stringByAppendingPathComponent:@"Documents/Movie.m4v"];
unlink([pathToMovie UTF8String]);
NSURL *movieURL = [NSURL fileURLWithPath:pathToMovie];

movieWriter = [[GPUImageMovieWriter alloc] initWithMovieURL:movieURL size:CGSizeMake(1920.0, 1280.0)];
[filter addTarget:movieWriter];

movieWriter.shouldPassthroughAudio = YES;
movieFile1.audioEncodingTarget = movieWriter;
[movieFile1 enableSynchronizedEncodingUsingMovieWriter:movieWriter];

[movieWriter startRecording];
[movieFile1 startProcessing];
[movieFile2 startProcessing];


[movieWriter setCompletionBlock:^{

   [filter removeTarget:movieWriter];
   [movieWriter finishRecording];
}];
Community
  • 1
  • 1
user2869423
  • 31
  • 2
  • 3
  • Please find my code... displayView is a UIView that I have programmatically created in the center of one of the viewcontrollers, but the video is not playing in the view. It just shows a frame and never plays the video. Any help is greatly appreciated. Thanks – user2869423 Oct 24 '13 at 04:22
  • I went past the crash by simply switching the ordering of [movieFile startProcessing]. But now the app goes into memory leak loop and eventually is terminated due to memory pressure. Instruments is pointing at [AVAssetWriterInput _helper] as the caller of the leak. Any clues are appreciated. – user2869423 Oct 25 '13 at 20:11
0

Ok, I have a few ideas for you.

When you say "it just shows a frame and never plays the video" we have a good indication that your entire processing pipeline from start to finish is functional exactly once, then stops working.

That tells us that you are stringing things together correctly, but some of the components don't exist longer than a single frame buffer cycle, and subsequently the whole process stops.

it looks like filter and movieWriter are scoped to the class (I'm assuming they're not properties from the lack of an underscore, _filter and _movieWriter). So they will live on after this method has finished (correct me if I'm wrong...)

I think where you are encountering trouble is your (GPUImageView*)displayView

This should probably be declared as a class property (although it could work as just a variable) and then instantiated through the nib or the viewDidLoad method of the view controller.

As you have it now, this line: GPUImageView* filterView = (GPUImageView*)displayView; is making an assignment for filterView which is not used (and therefore unnecessary). It's not clear if displayView really is an instance of GPUImageView or if it will still be in existence when the current method finishes. (in fact you say it "is a UIView that I have programmatically created")

displayView will have to be a subclass of GPUImageView for this whole thing to work, and it will have to be scoped to the class, and not the method.

Declare it like this:

@property (strong, nonatomic)GPUImageView* displayView;

and then instantiate it and add it to your view hierarchy from within viewDidLoad

ryan cumley
  • 1,901
  • 14
  • 11
  • TL;DR simply casting displayView to GPUImageView might fool the compiler, but the app will absolutely NEED display view to be an actual subclass of GPUImageView to run. – ryan cumley Oct 24 '13 at 22:13
  • Two further points that I think you'll encounter once you get it running, calling finishRecording from within the completion block of a GPUImageMovieWriter is likely to put you in an infinite loop of calling the completion block.. – ryan cumley Oct 24 '13 at 22:18
  • And you might want to consider - (id)initWithMovieURL:(NSURL *)newMovieURL size:(CGSize)newSize fileType:(NSString *)newFileType outputSettings:(NSMutableDictionary *)outputSettings; for finer grained control over the movieWriter – ryan cumley Oct 24 '13 at 22:19
  • I tried declaring displayView(btw, it is a property) as GPUImageView as well but the result did not change. But I would atleast like to be able to write the output video to file so that I cn play it. I am unable to write it successfully. If remove the completion block for the movieWriter, it does not give me an error but the output file is empty. If I give the completion block, it crashes with the following error: – user2869423 Oct 25 '13 at 03:34
  • I did change my code to use weakSelf while referencing self in the completion block. The result did not change. Thanks. – user2869423 Oct 25 '13 at 03:49
0
if (outputPath) {
                finalURL = [[stongObj tempFileURL] copy];
                DebugLog(@"Start Filter Processing :%@",finalURL);
                DebugLog(@"movieUrl :%@",movieUrl);

         //   [CSUtils removeChuckFilePaths:@[outputPath]];


            //Create Image Movie Object
            _movieFile = [[GPUImageMovie alloc] initWithURL:outputPath];
            //_movieFile = [[GPUImageMovie alloc] initWithURL:[[NSBundle mainBundle] URLForResource:@"videoviewdemo" withExtension:@"mp4"]];
            _movieFile.runBenchmark = NO;
            _movieFile.playAtActualSpeed = YES;
            _movieFile.delegate = self;

            //Movie Writer Object
            _movieWriter = [[GPUImageMovieWriter alloc] initWithMovieURL:finalURL size:CGSizeMake([UIScreen mainScreen].bounds.size.height,[UIScreen mainScreen].bounds.size.height)];
            //_movieWriter.delegate = self;

            //Create Selecetive GPU Image Filter
            [stongObj setGpuOutputFilter:selectedVideoFilterType];

            //Create Group Filter
            groupFilter = [[GPUImageFilterGroup alloc] init];
            [groupFilter addTarget:imageOutputFilter];

            // Only Single Filter is implemented.
            //Apply Initial and Terminal Filter
            [(GPUImageFilterGroup *)groupFilter setInitialFilters:[NSArray arrayWithObject:imageOutputFilter]];
            [(GPUImageFilterGroup *)groupFilter setTerminalFilter:imageOutputFilter];

            //_movieWriter -> groupFilter ->_movieFile
            [_movieFile addTarget:groupFilter];
            [groupFilter addTarget:_movieWriter];

            _movieWriter.shouldPassthroughAudio = YES;
            _movieFile.audioEncodingTarget = _movieWriter;
            [_movieFile enableSynchronizedEncodingUsingMovieWriter:_movieWriter];

            //Start Recording
            [_movieWriter startRecording];
            //Start Processing
            [_movieFile startProcessing];

            __weak typeof(self) weekSelf=self;
            [_movieWriter setCompletionBlock:^{

                __strong typeof(self) stongSelf=weekSelf;

                DebugLog(@"Movie Write Completed");
                //Finish Recording.
                [stongSelf.movieWriter finishRecording];

                //Release all object
                // [self releaseAllObject];

                //remove movieUrl,audioUrl,outputPath
                [CSUtils removeChuckFiles:@[movieUrl,audioUrl,outputPath]];

            }];

[_movieFile startProcessing]; app get crash in iOS 8 on this line but working fine on iOS 7

0

@Seasia Creative ,I have no enough reputation to add a comment by that list,I create a new list to answer U. I check the output URL,console log "/var~~~~/tmpmerge.mp4",so i realize that ,i miss a "/" --->"/var~~~~/tmp/merge.mp4". If the url is no correct, project runs into the same error. hope to help some.

aKerdi
  • 61
  • 1
  • 3