Ios 减少AVAssetWriter的内存使用

Ios 减少AVAssetWriter的内存使用,ios,objective-c,avassetwriter,cvpixelbuffer,Ios,Objective C,Avassetwriter,Cvpixelbuffer,正如标题所说,我在写作和记忆方面遇到了一些问题 关于我的环境/要求的一些注意事项: 我不是在使用ARC,但如果有一种方法可以简单地使用它并使其全部工作,我完全支持它。不过,我的尝试并没有产生任何影响。我将在其中使用它的环境要求尽快最小化/释放内存 目标C是一项要求 内存使用率必须尽可能低,在我的设备(iPhoneX)上测试时,它现在占用的300mb内存是不稳定的 代码 下面是截图时使用的代码 保留在内存中的问题/项目 在整个处理过程中占用大量内存的大部分内容似乎都是在开始时分配的 所以在这

正如标题所说,我在写作和记忆方面遇到了一些问题

关于我的环境/要求的一些注意事项:

  • 我不是在使用ARC,但如果有一种方法可以简单地使用它并使其全部工作,我完全支持它。不过,我的尝试并没有产生任何影响。我将在其中使用它的环境要求尽快最小化/释放内存
  • 目标C是一项要求
  • 内存使用率必须尽可能低,在我的设备(iPhoneX)上测试时,它现在占用的300mb内存是不稳定的
代码 下面是截图时使用的代码

保留在内存中的问题/项目 在整个处理过程中占用大量内存的大部分内容似乎都是在开始时分配的

所以在这一点上,我觉得问题不在于我的代码。我个人控制的代码似乎不是问题,即加载图像、创建缓冲区、释放这些似乎都不是内存有问题的地方。例如,如果我在仪器中标记上述时间之后的大部分时间,则内存是稳定的,并且没有任何内存保留

持续5mb的唯一原因是它在标记期结束后被释放

现在怎么办? 实际上,我开始写这个问题的重点是我的代码是否正确地发布了内容,但现在看来这很好。那么我现在有什么选择呢

  • 我是否可以在当前代码中配置一些东西来降低内存需求
  • 我的编写器/输入设置是否有问题
  • 我需要用一种完全不同的方式制作视频才能让它工作吗
关于使用CVPixelBufferPool的注意事项 在CVPixelBufferCreate Apple的文档中,声明:

如果需要创建和释放大量像素缓冲区,则应使用像素缓冲池(请参阅CVPixelBufferPool)以高效重用像素缓冲区内存

我也尝试过这个,但是我没有看到内存使用的变化。更改池的属性似乎也没有任何效果,因此有一个很小的可能性,我实际上没有100%正确地使用它,尽管与联机代码相比,至少看起来我是这样。输出文件可以正常工作

代码在这里

这是一个稍微不同的版本,我用稍微不同的方式设置了池

更新1 因此,我对跟踪进行了更深入的研究,以找出大部分分配的来源。这是一个带注释的图像:

外卖是:

  • 空间未“与”AVAssetWriter一起分配
  • 在处理开始后的500ms内分配了在结束前保持的500mb
  • 这似乎是在AVAssetWriter内部完成的
  • 我已将.trace文件上载到此处:

  • 创建调度队列时,请确保创建了具有自动租赁池的队列。将
    DISPATCH\u QUEUE\u SERIAL
    替换为
    DISPATCH\u QUEUE\u SERIAL\u替换为\u AUTORELEASE\u POOL

  • for
    循环的每个迭代也包装到自动释放池中

  • 像这样:

    [assetWriterInput requestMediaDataWhenReadyOnQueue:recordingQueue usingBlock:^{
            for (int i = 1; i < 200; ++i) {
                @autoreleasepool {
                    while (![assetWriterInput isReadyForMoreMediaData]) {
                        [NSThread sleepForTimeInterval:0.01]; 
                    }
                    NSString *path = [NSString stringWithFormat:@"/Users/jontelang/Desktop/SnapperVideoDump/frames/frame_%i.jpg", i];
                    UIImage *image = [UIImage imageWithContentsOfFile:path];
                    CGImageRef ref = [image CGImage];
                    CVPixelBufferRef buffer = [self pixelBufferFromCGImage:ref pool:writerAdaptor.pixelBufferPool];
                    CMTime presentTime = CMTimeAdd(CMTimeMake(i, 60), CMTimeMake(1, 60));
                    [writerAdaptor appendPixelBuffer:buffer withPresentationTime:presentTime];
                    CVPixelBufferRelease(buffer);
                }
            }
            [assetWriterInput markAsFinished];
            [assetWriter finishWritingWithCompletionHandler:^{}];
        }];
    
    [assetWriterInput RequestMediaDataWhenRepayonQueue:recordingQueue usingBlock:^{
    对于(int i=1;i<200;++i){
    @自动释放池{
    而(![assetWriterInput已准备好获取更多MediaData]){
    [NSThread sleepForTimeInterval:0.01];
    }
    NSString*path=[NSString stringWithFormat:@”/Users/jontelang/Desktop/snapervideodump/frames/frame_%i.jpg“,i];
    UIImage*image=[UIImage imageWithContentsOfFile:path];
    CGImageRef ref=[图像CGImage];
    CVPixelBufferRef buffer=[self pixelBufferFromCGImage:ref pool:writerAdaptor.pixelBufferPool];
    CMTime presentTime=CMTimeAdd(CMTimeMake(i,60),CMTimeMake(1,60));
    [writerAdaptor appendPixelBuffer:BufferwithPresentationTime:presentTime];
    CVPixelBufferRelease(缓冲区);
    }
    }
    [assetWriterInput标记已完成];
    [assetWriter finishWritingWithCompletionHandler:^{}];
    }];
    
    不,我看到应用程序中的峰值约为240 mb。这是我第一次使用这个分配-很有趣


    我正在使用AssetWriter通过流式传输cmSampleBuffer:cmSampleBuffer来编写视频文件。它通过摄像头CaptureOutput Realtime从AVCaptureVideoDataOutputSampleBufferDelegate获取。

    虽然我还没有找到实际问题,但我在这个问题中描述的内存问题通过在实际设备上而不是模拟器上进行解决。

    感谢您的回复,不幸的是,我没有看到这些更改带来的任何不同结果。为了更好地衡量,我还尝试使用DISPATCH\u autorelease\u frequency\u WORK\u项调整队列的自动释放频率。没有变化。在这种情况下,最好检查Xcode中的内存图,看看谁持有这些对象的引用。我不确定问题是否在for循环中,因为在第二个屏幕截图中,分配给它的内存似乎及时释放了。不过我会查一下内存图,我也忘了。谢谢。这里有一些想法,看看从0到300兆字节的内存大小,你可能需要释放中间的一些进程?或者使用assetwriter为特定工作创建一个视频,然后编写另一个视频,然后合并在一起。我在创建具有可变轨迹的assetwriter时遇到了一些问题,所以我在前一段时间考虑过这个问题。AssetWriter需要是单个实例,所以需要是线性的。您介意上传.trace文件吗?我有一些更新。似乎,当我在ac上运行它时