palusik
palusik

Reputation: 111

AVAssetWriter memory error

I have few methods that are supposed to write video in mov file to temp dir, but after ~15 sec. I'm getting errors:

Then app is crashing. I'm stuck and have no idea what is wrong...

- (void) saveVideoToFileFromBuffer:(CMSampleBufferRef) buffer {


    if (!movieWriter) {

        NSString *moviePath = [NSString stringWithFormat:@"%@tmpMovie", NSTemporaryDirectory()];

        if ([[NSFileManager defaultManager] fileExistsAtPath:moviePath])
            [self removeMovieAtPath:moviePath];

        NSError *error = nil;

        movieWriter = [[AVAssetWriter alloc] initWithURL:[NSURL fileURLWithPath:moviePath] fileType: AVFileTypeQuickTimeMovie error:&error];
        if (error) {

            m_log(@"Error allocating AssetWriter: %@", [error localizedDescription]);

        } else {

            CMFormatDescriptionRef description = CMSampleBufferGetFormatDescription(buffer);

            if(![self setUpMovieWriterObjectWithDescriptor:description])
                    m_log(@"ET go home, no video recording!!");
        }

    }

    if (movieWriter.status != AVAssetWriterStatusWriting) {

        [movieWriter startWriting];

        [movieWriter startSessionAtSourceTime:kCMTimeZero];

        apiStatusChangeIndicator = NO;

    }

    if (movieWriter.status == AVAssetWriterStatusWriting) {

        if (![movieInput appendSampleBuffer:buffer]) m_log(@"Failed to append sample buffer!");

    }


}

Rest of code:

- (BOOL) setUpMovieWriterObjectWithDescriptor:(CMFormatDescriptionRef) descriptor {

    CMVideoDimensions dimensions = CMVideoFormatDescriptionGetDimensions(descriptor);

    NSDictionary *compressionSettings = [NSDictionary dictionaryWithObjectsAndKeys: AVVideoProfileLevelH264Baseline31,AVVideoProfileLevelKey,
                                        [NSNumber numberWithInteger:30], AVVideoMaxKeyFrameIntervalKey, nil];
    //AVVideoProfileLevelKey set because of errors


    NSDictionary *videoSettings = [NSDictionary dictionaryWithObjectsAndKeys:AVVideoCodecH264, AVVideoCodecKey,[NSNumber numberWithInt:dimensions.width], AVVideoWidthKey,
                                    [NSNumber numberWithInt:dimensions.height], AVVideoHeightKey, compressionSettings, AVVideoCompressionPropertiesKey, nil];


    if ([movieWriter canApplyOutputSettings:videoSettings forMediaType:AVMediaTypeVideo]) {

        movieInput = [[AVAssetWriterInput alloc] initWithMediaType:AVMediaTypeVideo outputSettings:videoSettings];
        movieInput.expectsMediaDataInRealTime = YES;

        if ([movieWriter canAddInput:movieInput]) {

            [movieWriter addInput:movieInput];
        } else {

            m_log(@"Couldn't apply video input to Asset Writer!");

            return NO;
        }

    } else {

        m_log(@"Couldn't apply video settings to AVAssetWriter!");

        return NO;
    }



    return YES;
}

Would be great if someone could point my mistake! Can share more code if needed. SampleBuffer comes from CIImage with filters.

Now new thing, I can record few seconds of movie and saved it, but it's all black screen...

UPDATE

Saving video works, but creating CMSampleBufferRef from CIImage fails. It's reason that I got green or black screen, here's the code:

- (CMSampleBufferRef) processCIImageToPixelBuffer:(CIImage*) image andSampleBuffer:(CMSampleTimingInfo) info{

    CVPixelBufferRef renderTargetPixelBuffer;

    CFDictionaryRef empty;
    CFMutableDictionaryRef attrs;

    empty = CFDictionaryCreate(kCFAllocatorDefault,
                               NULL,
                               NULL,
                               0,
                               &kCFTypeDictionaryKeyCallBacks,
                               &kCFTypeDictionaryValueCallBacks);

    attrs = CFDictionaryCreateMutable(kCFAllocatorDefault,
                                      1,
                                      &kCFTypeDictionaryKeyCallBacks,
                                      &kCFTypeDictionaryValueCallBacks);

    CFDictionarySetValue(attrs,
                         kCVPixelBufferIOSurfacePropertiesKey,
                         empty);

    CVReturn cvError = CVPixelBufferCreate(kCFAllocatorSystemDefault,
                                           [image extent].size.width,
                                           [image extent].size.height,
                                           kCVPixelFormatType_420YpCbCr8BiPlanarFullRange,
                                           attrs,
                                           &renderTargetPixelBuffer);
    if (cvError != 0) {

        m_log(@"Error when init Pixel buffer: %i", cvError);

    }

    CFRelease(empty);
    CFRelease(attrs);

    CVPixelBufferLockBaseAddress(renderTargetPixelBuffer, 0 );

    [_coreImageContext render:image toCVPixelBuffer:renderTargetPixelBuffer];

    CVPixelBufferUnlockBaseAddress(renderTargetPixelBuffer, 0 );

    CMVideoFormatDescriptionRef videoInfo = NULL;
    CMVideoFormatDescriptionCreateForImageBuffer(kCFAllocatorDefault, renderTargetPixelBuffer, &videoInfo);

    CMSampleBufferRef recordingBuffer;


    OSStatus cmError = CMSampleBufferCreateForImageBuffer(kCFAllocatorDefault, renderTargetPixelBuffer, true, NULL, NULL, videoInfo, &info, &recordingBuffer);

    if (cmError != 0 ) {

        m_log(@"Error creating sample buffer: %i", (int)cmError);
    }

    CVPixelBufferRelease(renderTargetPixelBuffer);
    renderTargetPixelBuffer = NULL;
    CFRelease(videoInfo);
    videoInfo = NULL;

    return recordingBuffer;
}

Upvotes: 0

Views: 1341

Answers (1)

anatoliy_v
anatoliy_v

Reputation: 1800

You should check your code with Profile tool. Especially for memory leaks. May be you do not release sample buffer:

CMSampleBufferInvalidate(buffer);
CFRelease(buffer);
buffer = NULL;

Upvotes: 4

Related Questions