Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unable to allocate pixelBuffer: -6661 in SCAssetExportSession #89

Closed
mjgaylord opened this issue Nov 26, 2014 · 14 comments
Closed

Unable to allocate pixelBuffer: -6661 in SCAssetExportSession #89

mjgaylord opened this issue Nov 26, 2014 · 14 comments

Comments

@mjgaylord
Copy link
Contributor

I am exporting videos using SCAssetExportSession and applying a filterGroup and I get this error intermittently. I am not sure what could be causing it.

Looking up error -6661 in the docs it is: kCVReturnInvalidArgument.

The underlying export session error is:

Error Domain=AVFoundationErrorDomain Code=-11800 "The operation could not be completed" UserInfo=0x16372100 {NSLocalizedDescription=The operation could not be completed, NSUnderlyingError=0x1634cb00 "The operation couldn’t be completed. (OSStatus error -12780.)", NSLocalizedFailureReason=An unknown error occurred (-12780)}

Does anyone have any idea why this could be happening?

My code is the following:

class func export(recordSession: SCRecordSession,
        withFilter filter: SCFilterGroup?, completion:(url: NSURL!, error : NSError?) -> Void) {
            let asset = recordSession.assetRepresentingRecordSegments()
            var exportSession = SCAssetExportSession(asset: asset)
            var exportFilter: SCFilterGroup = SCFilterGroup.filterGroupWithContentsOfURL(NSBundle.mainBundle().URLForResource("Plain", withExtension: "cisf"), groupName: "Plain")
            if let _filter = filter {
                exportFilter = _filter
            }
            exportSession.filterGroup = exportFilter
            exportSession.sessionPreset = SCAssetExportSessionPresetHighestQuality
            exportSession.outputUrl = recordSession.outputUrl
            exportSession.outputFileType = AVFileTypeMPEG4
            exportSession.keepVideoSize = true
            exportSession.exportAsynchronouslyWithCompletionHandler{
                completion(url: exportSession.outputUrl, error: exportSession.error)
            }
    }
@rFlex
Copy link
Owner

rFlex commented Nov 26, 2014

Like most of the time when getting an error code from a framework from Apple, it's pretty much either undocumented or not precise enough to help you figure out what's going on. Does it happen regardless of the filter group you set? What underlying SCFilters contains this filter group?

@mjgaylord
Copy link
Contributor Author

Yes it does seem to happen regardless of the filter type. The test cases I've been able to reproduce it on are on any of the CIPhoto filters e.g. SCFilter(name: "CIPhotoEffectNoir") and filters generated in CoreImageShop. But as I mentioned, it seems to be intermittent.

If I ignore the error the file still gets generated, but it has a visible stutter at the point where it fails.

I wasn't getting these errors in the older versions of SCRecorder, so it seems to be something new.

Here are my SCRecorder settings in case you are able to reproduce the error with them:

recorder.setActiveFormatWithFrameRate(26, width: 960, andHeight: 540, error: &error)

@rFlex
Copy link
Owner

rFlex commented Nov 26, 2014

Did you try using a record session that filed and export it again? I'd like to know if it's related to the recording or just the exporter.

@mjgaylord
Copy link
Contributor Author

Okay so I tried writing it to file first and then loading it for export and it looks like it is the exporter and not the recorder. It also seems a lot worse if I use 960x540 (almost every time) rather than on 1280x720 (1 out of 10 times it fails).

@rFlex
Copy link
Owner

rFlex commented Nov 26, 2014

So you have a specific file that fails almost every time when trying to export it? On which device?

@mjgaylord
Copy link
Contributor Author

It's on an iPhone 5. I've extracted a file that fails in case you are able to replicate the issue yourself: https://dl.dropboxusercontent.com/u/2186105/video-with-error.mp4

@rFlex
Copy link
Owner

rFlex commented Dec 1, 2014

I could not reproduce the bug, even on iPhone 5 using the following setup:

- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];

    [self compress];
}

- (void)compress {

    NSURL *assetUrl = [[NSBundle mainBundle] URLForResource:@"video-with-error" withExtension:@"mp4"];
    AVAsset *asset = [AVAsset assetWithURL:assetUrl];
    SCFilterGroup *exportFilter = [SCFilterGroup filterGroupWithFilter:[SCFilter filterWithName:@"CIPhotoEffectNoir"]];

    SCAssetExportSession *exportSession = [[SCAssetExportSession alloc] initWithAsset:asset];
    exportSession.filterGroup = exportFilter;
    exportSession.sessionPreset = SCAssetExportSessionPresetHighestQuality;
    exportSession.outputUrl = [[NSURL fileURLWithPath:NSTemporaryDirectory()] URLByAppendingPathComponent:@"output.mp4"];
    exportSession.outputFileType = AVFileTypeMPEG4;
    exportSession.keepVideoSize = YES;
    [exportSession exportAsynchronouslyWithCompletionHandler:^{
        if (exportSession.error == nil) {
            NSLog(@"Success");
        } else {
            NSLog(@"Error: %@", exportSession.error);
        }

        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            [self compress];
        });
    }];
}

Did you have more success while disabling the gpu on the SCAssetExportSession (exportSession.useGPUForRenderingFilters)? Are you playing any video while the processing is being done? If you choose to use the GPU (default behavior, way faster), the processing must be done with no other concurrent GPU intensive operations (like playing a video, animations...).

@mjgaylord
Copy link
Contributor Author

Ok, thanks for looking into this. And great library BTW. I will give your suggestion a try and see if things improve. This might be a separate issue but I do have a feeling there is something wrong with either the way I have set up my recorder or the recorder code itself, because I have been experiencing the audio going out of sync with the video on occasion. But only when I try and play the videos back using something like VLC. If I use quicktime, the video and audio streams stay in sync fine. This is a bit of an issue, since my videos are getting re-encoded on a server and the re-encoding process doesn't carry over whatever timing information is embedded in the mp4 file. The problem however, definitely lies in the recording/merging of the videos since the original, exported mp4 files go out of sync in VLC before re-encoding. I will see if I can narrow the issue down further and get back to you.

@rFlex
Copy link
Owner

rFlex commented Dec 1, 2014

Ok, thank you for investigating!

@mjgaylord
Copy link
Contributor Author

Looks like the audio and video going out of sync is a separate issue. I was able to replicate it with the sample SCRecorderExample project on the latest code. I will create a new issue for it.

I also tried using the GPU for exporting without luck, I will try get it to replicate the issue using the sample project too.

@rFlex
Copy link
Owner

rFlex commented Dec 5, 2014

I "managed" to get this issue on iPhone 5 iOS 7. You can temporary workaround this by setting a "maxFrameRate" in the videoConfiguration on the SCAssetExportSession to a value a little higher than the nominal frame rate (like 35 for a 30 fps video for instance). There is a bug where reading the AVComposition from the AVAssetReader gets two buffer at almost the same time (at the exact point where two assets are merged). Setting the maxFrameRate will automatically skip one frame. I though get a black frame between the two assets in the output video. I'm currently working on fixing this.

@mjgaylord
Copy link
Contributor Author

I also played around with it a bit and managed to prevent the issue using the sample code in the examples app. It's been 4 days without issue so far amongst our beta testers. For now, I am leaving it as is, as we need to submit to the AppStore next week. I haven't seen the pixel buffer issue since then.

Here is my recorder configuration code:

        var recorder = SCRecorder()
        recorder.sessionPreset = AVCaptureSessionPresetiFrame960x540
        recorder.maxRecordDuration = CMTimeMakeWithSeconds(20, 1)
        recorder.delegate = self
        recorder.frameRate = 26
        recorder.initializeRecordSessionLazily = true
        recorder.previewView = self.previewView

And here is my export code, the filter is a CoreImageShop filter with no changes, but using other filters works fine too:

        let currentFilter = SCFilterGroup.filterGroupWithContentsOfURL(NSBundle.mainBundle().URLForResource("Plain", withExtension: "cisf"), groupName: "Standard")
        var exportSession = SCAssetExportSession(asset:       recordSession.assetRepresentingRecordSegments())
        exportSession.filterGroup = currentFilter
        exportSession.sessionPreset = SCAssetExportSessionPresetHighestQuality
        exportSession.outputUrl = recordSession.outputUrl
        println("exportSession.outputUrl: \(exportSession.outputUrl)")
        exportSession.outputFileType = AVFileTypeMPEG4
        exportSession.keepVideoSize = true
        exportSession.exportAsynchronouslyWithCompletionHandler {
            completionHandler(exportSession.outputUrl, exportSession.error)
        }

@rFlex
Copy link
Owner

rFlex commented Dec 8, 2014

Fixed on last commit. Thank you so much for all the informations you provided!

@rFlex rFlex closed this as completed Dec 8, 2014
@glm4
Copy link

glm4 commented Feb 24, 2016

Im still having this issue, my code is the following:
My recorder has AVCaptureSessionPreset1280x720 preset.

SCAssetExportSession *exportSession = [[SCAssetExportSession alloc] initWithAsset:self.recordSession.assetRepresentingSegments];
        if(![currentFilter isEmpty]) {
            exportSession.videoConfiguration.filter = currentFilter;
        }
        exportSession.videoConfiguration.preset = SCPresetMediumQuality;
        exportSession.audioConfiguration.preset = SCPresetHighestQuality;
        exportSession.videoConfiguration.maxFrameRate = 35;

        NSString *exportPath = [NSTemporaryDirectory() stringByAppendingPathComponent:@"editedVideo.mov"];

        exportSession.outputUrl = [NSURL fileURLWithPath:exportPath];
        exportSession.outputFileType = AVFileTypeQuickTimeMovie;
        exportSession.contextType = SCContextTypeAuto;

        [exportSession exportAsynchronouslyWithCompletionHandler:^{
...
}];

Any thoughts?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants