AVAssetWriter 内存错误

Posted

技术标签:

【中文标题】AVAssetWriter 内存错误【英文标题】:AVAssetWriter memory error 【发布时间】:2014-07-15 12:53:22 【问题描述】:

我有几个方法应该将 mov 文件中的视频写入临时目录,但大约 15 秒后。我收到错误:

收到内存警告。 收到内存警告。 收到内存警告。 收到内存警告。

然后应用程序崩溃了。我被卡住了,不知道出了什么问题......

- (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!");

    



其余代码:

- (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;

如果有人能指出我的错误,那就太好了!如果需要,可以共享更多代码。 SampleBuffer 来自带有过滤器的 CIImage。

现在新东西,我可以录制几秒钟的电影并保存,但它都是黑屏......

更新

保存视频有效,但从 CIImage 创建 CMSampleBufferRef 失败。这是我得到绿屏或黑屏的原因,这是代码:

- (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;

【问题讨论】:

【参考方案1】:

您应该使用 Profile 工具检查您的代码。特别是对于内存泄漏。可能是您没有释放样本缓冲区:

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

【讨论】:

这是个好电话。我已经分析了泄漏的应用程序,尽我所能释放/空,现在没有内存警告,但我仍然可以找到使我的视频全绿的错误。这就是我所得到的,绿屏n秒。知道为什么吗? 我已经设法使用 AVAssetWriterInputPixelBufferAdaptor 并从 CVPixelBufferRef 保存来做到这一点,因此创建 CMSampleBuffer 形式 CIImage (CIImage -> CVPixelBuffer -> CMSampleBuffer) 只需要 CIImage 到 CVPixelBuffer。

以上是关于AVAssetWriter 内存错误的主要内容,如果未能解决你的问题,请参考以下文章

AVAssetWriter 未知错误

从使用 AVAssetWriter 创建的视频生成缩略图

AVAssetWriter 元数据日期问题

AVAssetWriter 记录设置不像 AVAudioRecorder 那样工作

我的 AVFoundation/AVCaptureSession 泄漏内存在哪里?

server2008物理内存使用82%导致程序内存错误