菜鸟教程小白 发表于 2022-12-13 11:42:54

ios - CMSampleBufferGetImageBuffer 中的内存泄漏


                                            <p><p>我每 N 个视频帧从 <em>CMSampleBufferRef</em> 视频缓冲区中获取一个 <em>UIImage</em>,例如:</p>

<pre><code>- (void)imageFromVideoBuffer:(void(^)(UIImage* image))completion {
    CMSampleBufferRef sampleBuffer = _myLastSampleBuffer;
    if (sampleBuffer != nil) {
      CFRetain(sampleBuffer);
      CIImage *ciImage = ;
      _lastAppendedVideoBuffer.sampleBuffer = nil;
      if (_context == nil) {
            _context = ;
      }
      CVPixelBufferRef buffer = CMSampleBufferGetImageBuffer(sampleBuffer);
      CGImageRef cgImage = [_context createCGImage:ciImage fromRect:
                              CGRectMake(0, 0, CVPixelBufferGetWidth(buffer), CVPixelBufferGetHeight(buffer))];
      __block UIImage *image = ;

      CGImageRelease(cgImage);
      CFRelease(sampleBuffer);

      if(completion) completion(image);

      return;
    }
    if(completion) completion(nil);
}
</code></pre>

<p>XCode 和 Instruments 检测到内存泄漏,但我无法摆脱它。
我照常发布 CGImageRef 和 CMSampleBufferRef:</p>

<pre><code>CGImageRelease(cgImage);
CFRelease(sampleBuffer);
</code></pre>

<p><strong>[更新]</strong>
我放入 <code>AVCapture</code> 输出回​​调以获取 <code>sampleBuffer</code>。</p>

<pre><code>- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection {
    if (captureOutput == _videoOutput) {
      _lastVideoBuffer.sampleBuffer = sampleBuffer;
      id&lt;CIImageRenderer&gt; imageRenderer = _CIImageRenderer;

      dispatch_async(dispatch_get_main_queue(), ^{
            @autoreleasepool {
                CIImage *ciImage = nil;
                ciImage = ;
                if(_context==nil) {
                  _context = ;
                }
                CGImageRef processedCGImage = [_context createCGImage:ciImage
                                                             fromRect:];
                //UIImage *image=;
                CGImageRelease(processedCGImage);
                NSLog(@&#34;Captured image %@&#34;, ciImage);
            }
      });
</code></pre>

<p>泄露的代码是 <code>createCGImage:ciImage</code>:</p>

<pre><code>CGImageRef processedCGImage = [_context createCGImage:ciImage
                                                             fromRect:];
</code></pre>

<p>即使有一个 <code>autoreleasepool</code>、<code>CGImage</code> 引用的 <code>CGImageRelease</code> 和一个 <code>CIContext</code> 作为实例属性。</p>

<p>这似乎与此处解决的问题相同:<a href="https://stackoverflow.com/questions/25826755/cant-save-ciimage-to-file-on-ios-without-memory-leaks" rel="noreferrer noopener nofollow">Can&#39;t save CIImage to file on iOS without memory leaks</a> </p>

<p>[更新]
泄漏似乎是由于一个错误。这个问题在
<a href="https://forums.developer.apple.com/message/50981#50981" rel="noreferrer noopener nofollow">Memory leak on CIContext createCGImage at iOS 9?</a> </p>

<p>一个示例项目显示了如何重现此泄漏:<a href="http://www.osamu.co.jp/DataArea/VideoCameraTest.zip" rel="noreferrer noopener nofollow">http://www.osamu.co.jp/DataArea/VideoCameraTest.zip</a> </p>

<p>最后的评论确保</p>

<blockquote>
<p>It looks like they fixed this in 9.1b3. If anyone needs a workaround
that works on iOS 9.0.x, I was able to get it working with this:</p>
</blockquote>

<p>在测试代码中(在本例中为 Swift):</p>

<pre><code>[self.stillImageOutput captureStillImageAsynchronouslyFromConnection:videoConnection completionHandler: ^(CMSampleBufferRef imageSampleBuffer, NSError *error)
    {
      if (error) return;

      __block NSString *filePath = .timeIntervalSince1970]];

      NSData *imageData = ;
      dispatch_async(dispatch_get_main_queue(), ^
      {

            @autoreleasepool
            {
                CIImage *enhancedImage = ;

                if (!enhancedImage) return;

                static CIContext *ctx = nil; if (!ctx) ctx = ;

                CGImageRef imageRef = ;

                UIImage *image = ;

                [ createFileAtPath:filePath contents:UIImageJPEGRepresentation(image, 0.8) attributes:nil];

                CGImageRelease(imageRef);
            }
      });
    }];
</code></pre>

<p>iOS9.0 的解决方法应该是</p>

<pre><code>extension CIContext {
    func createCGImage_(image:CIImage, fromRect:CGRect) -&gt; CGImage {
      let width = Int(fromRect.width)
      let height = Int(fromRect.height)

      let rawData =UnsafeMutablePointer&lt;UInt8&gt;.alloc(width * height * 4)
      render(image, toBitmap: rawData, rowBytes: width * 4, bounds: fromRect, format: kCIFormatRGBA8, colorSpace: CGColorSpaceCreateDeviceRGB())
      let dataProvider = CGDataProviderCreateWithData(nil, rawData, height * width * 4) {info, data, size in UnsafeMutablePointer&lt;UInt8&gt;(data).dealloc(size)}
      return CGImageCreate(width, height, 8, 32, width * 4, CGColorSpaceCreateDeviceRGB(), CGBitmapInfo(rawValue: CGImageAlphaInfo.PremultipliedLast.rawValue), dataProvider, nil, false, .RenderingIntentDefault)!
    }
}
</code></pre></p>
                                    <br><hr><h1><strong>Best Answer-推荐答案</ strong></h1><br>
                                            <p><p>我们在创建的应用程序中遇到了类似的问题,我们正在使用 OpenCV 处理特征关键点的每一帧,并每隔几秒钟发送一帧。运行一段时间后,我们最终会收到很多内存压力消息。 </p>

<p>我们设法通过在它自己的自动释放池中运行我们的处理代码来纠正这个问题(jpegDataFromSampleBufferAndCrop 所做的事情与您正在做的事情类似,但增加了裁剪):</p>

<pre><code>- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection
{
      @autoreleasepool {

            if ( &lt; -kContinuousRateInSeconds) {

                NSData *imageData = ;

                if (imageData) {
                  ;
                }

                self.lastFrameSentAt = ;

                imageData = nil;
            }
      }
    }
}
</code></pre></p>
                                   
                                                <p style="font-size: 20px;">关于ios - CMSampleBufferGetImageBuffer 中的内存泄漏,我们在Stack Overflow上找到一个类似的问题:
                                                        <a href="https://stackoverflow.com/questions/32685756/" rel="noreferrer noopener nofollow" style="color: red;">
                                                                https://stackoverflow.com/questions/32685756/
                                                        </a>
                                                </p>
                                       
页: [1]
查看完整版本: ios - CMSampleBufferGetImageBuffer 中的内存泄漏