【问题标题】:Show Camera streaming from frames by using UIImageView memory leak crash使用 UIImageView 内存泄漏崩溃从帧中显示相机流
【发布时间】:2025-12-26 10:30:12
【问题描述】:

我正在使用 QCAR 库,并且我在每一帧中都从库中获取相机帧。

我试图通过在我的UIImageView* mCurFrameView 上使用setImage 来显示这个框架。起初这是可行的,我可以看到帧运行平稳,但 20 秒后它崩溃了。

有时我会收到EXC_BAD_ACCESS

int retVal = UIApplicationMain(argc, argv, nil, nil); 

有时它只是 gdb 并暂停。

有时在他崩溃之前我会得到

2012-02-24 15:59:15.726 QRAR_nextGen[226:707] Received memory warning.

这是我的代码:

-(void)SaveCurrentFrame:(UIImage*)image
{

        mCurFrameView.image = image;

}


- (void)renderFrameQCAR
{

   cout<<"I am starting"<<endl;


QCAR::State state = QCAR::Renderer::getInstance().begin();


QCAR::setFrameFormat(QCAR::RGB888, true);

const QCAR::Image *image = state.getFrame().getImage(1);// 0: YUV, 1: Grayscale image

if (image)
{
    const char *data = (const char *)image->getPixels();
    int width = image->getWidth(); int height = image->getHeight();

    colorSpace = CGColorSpaceCreateDeviceRGB();
    bitmapInfo = kCGBitmapByteOrderDefault;
    provider = CGDataProviderCreateWithData(NULL, data, width*height*3, NULL);
    intent = kCGRenderingIntentDefault;
    imageRef = CGImageCreate(width, height, 8, 8*3, width * 3, colorSpace, bitmapInfo,    provider, NULL, NO, intent);

    mCurFrame = [UIImage imageWithCGImage:imageRef];


    cout<<"I am waiting"<<endl;
   [self performSelectorOnMainThread:@selector(SaveCurrentFrame:) withObject:mCurFrame waitUntilDone:YES];

}

我尝试了几件事:显示 CALayer 以显示相机、释放、保留、自动释放、定义和不定义属性和合成。

如果有人能帮助我,我将不胜感激。我正在失去理智。非常感谢。

【问题讨论】:

    标签: ios memory-leaks uiimage vuforia


    【解决方案1】:

    您没有释放(泄漏)每个 CGDataProvider,这意味着您将所有图像数据存储在内存中。尝试在 performSelectorOnMainThread 之后执行 CGDataProviderRelease(provider)。

    【讨论】:

      【解决方案2】:

      也许你错过了这个:

         QCAR::Renderer::getInstance().end();
      

      这是一个适用于 iPhone 4S/5 iOS 6 的 sn-p

      - (void)renderFrameIntoImage {
         QCAR::State state = QCAR::Renderer::getInstance().begin();
         QCAR::setFrameFormat(QCAR::GRAYSCALE, true);
         const QCAR::Image *image = state.getFrame().getImage(0); // 0: YUV, 1: Grayscale image
         const char *data = (const char *)image->getPixels();
         int width = image->getWidth(); int height = image->getHeight();
         CGColorSpace *colorSpace = CGColorSpaceCreateDeviceGray();
         CGBitmapInfo bitmapInfo = kCGBitmapByteOrderDefault;
         CGDataProvider *provider = CGDataProviderCreateWithData(NULL, data, width*height, NULL);
         CGColorRenderingIntent intent = kCGRenderingIntentDefault;
         CGImageRef imageRef = CGImageCreate(width, height, 8, 8, width * 1, colorSpace, bitmapInfo, provider, NULL, NO, intent);
         UIImage *myImage = [UIImage imageWithCGImage:imageRef];
         QCAR::Renderer::getInstance().end();
         UIImageWriteToSavedPhotosAlbum(myImage, nil, nil, NULL);
      }
      

      问候...

      【讨论】:

        【解决方案3】:

        你有三个泄漏。

        您必须为每个带有单词Create 的CoreFoundation 方法调用Release 方法。

        1. CGColorSpaceRelease(colorSpace);
        2. CGDataProviderRelease(provider);
        3. CGImageRelease(imageRef);

        进行 QCAR::Image 到 UIImage 转换的 C++ 方法

        inline UIImage *imageWithQCARCameraImage(const QCAR::Image *cameraImage)
        {
            UIImage *image = nil;
        
            if (cameraImage) {
                CGColorSpaceRef colorSpace = NULL;
                QCAR::PIXEL_FORMAT pixelFormat = cameraImage->getFormat();
        
                int bitsPerPixel = QCAR::getBitsPerPixel(pixelFormat);
        
                switch (pixelFormat) {
                    case QCAR::RGB888:
                        colorSpace = CGColorSpaceCreateDeviceRGB();
                        break;
                    case QCAR::GRAYSCALE:
                        colorSpace = CGColorSpaceCreateDeviceGray();
                        break;
                    case QCAR::YUV:
                    case QCAR::RGB565:
                    case QCAR::RGBA8888:
                    case QCAR::INDEXED:
                        std::cerr << "Image format conversion not implemented." << std::endl;
                        break;
                    case QCAR::UNKNOWN_FORMAT:
                        std::cerr << "Image format unknown." << std::endl;
                        break;
                }
        
                float width = cameraImage->getWidth();
                float height = cameraImage->getHeight();
                int bytesPerRow = cameraImage->getStride();
                const void *baseAddress = cameraImage->getPixels();
                size_t totalBytes = QCAR::getBufferSize(width, height, pixelFormat);
        
                if (bitsPerPixel > 0 && colorSpace != NULL) {
                    CGDataProviderRef provider = CGDataProviderCreateWithData(NULL,
                                                                              baseAddress,
                                                                              totalBytes,
                                                                              NULL);
        
                    int bitsPerComponent = 8;
                    CGBitmapInfo bitmapInfo = kCGBitmapByteOrderDefault | kCGImageAlphaNone;
                    CGColorRenderingIntent renderingIntent = kCGRenderingIntentDefault;
                    CGImageRef imageRef = CGImageCreate(width,
                                                        height,
                                                        bitsPerComponent,
                                                        bitsPerPixel,
                                                        bytesPerRow,
                                                        colorSpace,
                                                        bitmapInfo,
                                                        provider,
                                                        NULL,
                                                        NO,
                                                        renderingIntent);
        
                    image = [UIImage imageWithCGImage:imageRef];
                    CGColorSpaceRelease(colorSpace);
                    CGDataProviderRelease(provider);
                    CGImageRelease(imageRef);
                }
            }
        
            return image;
        }
        

        【讨论】: