2

I am creating this app that is a camera. Because it is being created for iOS 9, I have to test it on an old device. In that case an iPad 3. The app works perfectly on a new iPad Pro 9.7 but fails to write video after a while on iPad 3.

What happens is, the app starts writing frames fine but suddenly fails.

I am using this method to store each frame:

- (void)writeToFileFrame:(CIImage *) finalImage
          withSampleTime:(CMSampleTimingInfo)sampleTime
                 andSize:(CGSize)size
{

  if (!_assetWriter) {
    if (![self initializeAssetWriter]) {
      return;
    }
  }

  // convert CIImage to CMSampleBufferRef and save
  CGRect extent = [finalImage extent];
  CGFloat width = CGRectGetWidth(extent);
  CGFloat height  = CGRectGetHeight(extent);

  if ((width == 0) && (height == 0)) return;


  NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
                           [NSDictionary dictionary], (id)kCVPixelBufferIOSurfacePropertiesKey,
                           @(YES), kCVPixelBufferCGImageCompatibilityKey,
                           @(YES), kCVPixelBufferCGBitmapContextCompatibilityKey,
                           kCVImageBufferYCbCrMatrix_ITU_R_601_4, kCVImageBufferYCbCrMatrixKey,
                           kCVImageBufferColorPrimaries_ITU_R_709_2, kCVImageBufferColorPrimariesKey, nil];

  // Initialize the video input if this is not done yet
  if (!_readyToWriteVideo) {
    _readyToWriteVideo = [self setupAssetWriterVideoInputWithSize:size];
  }

  CVPixelBufferRef pixelBuffer = NULL;

  CVPixelBufferCreate(kCFAllocatorSystemDefault, width, height, kCVPixelFormatType_32BGRA, (__bridge CFDictionaryRef) options, &pixelBuffer);

  CVPixelBufferLockBaseAddress( pixelBuffer, 0 );
  [_ciContext render:finalImage toCVPixelBuffer:pixelBuffer];
  CVPixelBufferUnlockBaseAddress( pixelBuffer, 0 );

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

  CMSampleBufferRef oBuf;
  OSStatus status = CMSampleBufferCreateForImageBuffer(kCFAllocatorDefault, pixelBuffer, true, NULL, NULL, videoInfo, &sampleTime, &oBuf);
  CVPixelBufferRelease(pixelBuffer);
  CFRelease(videoInfo);

  if (status != noErr) {
    NSLog(@"error creating CMSampleBufferCreateForImageBuffer");
    CFRelease(oBuf);
    return;
  }

  // Write video data to file only when all the inputs are ready
  if ([self inputsReadyToWriteToFile]) {
    if (_assetWriter.error) {
      NSLog(@"%@",[_assetWriter.error localizedDescription]);
      return;
    }
    [self writeSampleBuffer:oBuf ofType:AVMediaTypeVideo];
  }

  CFRelease(oBuf);

}


- (void)writeSampleBuffer:(CMSampleBufferRef)sampleBuffer ofType:(NSString *)mediaType
{  
  if ( _assetWriter.status == AVAssetWriterStatusUnknown ) {
    NSLog(@"unknown state");
    // If the asset writer status is unknown, implies writing hasn't started yet, hence start writing with start time as the buffer's presentation timestamp
    if ([_assetWriter startWriting]) {
      [_assetWriter startSessionAtSourceTime:CMSampleBufferGetPresentationTimeStamp(sampleBuffer)];
    } else {
          // error
     }
  }

  if ( _assetWriter.status == AVAssetWriterStatusWriting ) {
    // If the asset writer status is writing, append sample buffer to its corresponding asset writer input
    if (mediaType == AVMediaTypeVideo) {
      if (_assetWriterVideoInput.readyForMoreMediaData) {
        if (![_assetWriterVideoInput appendSampleBuffer:sampleBuffer]) {
          NSLog(@"error: %@", [_assetWriter.error localizedFailureReason]); //Ⓐ
        }
      }
    }
    else if (mediaType == AVMediaTypeAudio) {
      if (_assetWriterAudioInput.readyForMoreMediaData) {
        if (![_assetWriterAudioInput appendSampleBuffer:sampleBuffer]) {
                      // error
        }
      }
    }
  }

  if ( _assetWriter.status == AVAssetWriterStatusFailed ) {
    NSLog(@"error"); 
  }

}

This works fine on iPad Pro 9.7 but on iPad 3 it hits line Ⓐ, failing miserably, after writing frames correctly for about 5 seconds.

Fails with error -536870211, that is obviously an unknown error.

I have checked the apps for leaks and there is none.

Any ideas?

NOTE: I have discovered now that the problems only shows if I am writing frames from the rear camera (HD). If I switch to the front camera VGA (640x480) it works fine. So it has to do with memory allocations but I have checked that with instruments and the app is using about 12 MB of memory and this value is more or less constant. No leaks.

rmaddy
  • 314,917
  • 42
  • 532
  • 579
Duck
  • 34,902
  • 47
  • 248
  • 470
  • I have no idea. :) But I do have an iPad 3. In comparison to iPad Pro, it is: (1) grossly underpowered [frame-dropping issue?] (2) highly limited as to RAM memory (3) single-core [threading issue?] (4) 32-bit [bitness issue?] – matt Mar 27 '17 at 15:24
  • ok I agree but if the app is compatible with iOS 9 it will have to run on iPad 3. – Duck Mar 27 '17 at 15:28

1 Answers1

1

That error is kIOReturnNoMemory

Memory can't be allocated (0xe00002bd).Value: 0xe00002bd (-536870211)

so it sounds like you're using too much memory. You need to make sure that you're retaining as few sample buffers and their derivatives for as short a period of time as possible.

The Instruments app memory and GPU tools and Xcode's memory gauges should be helpful too.

Rhythmic Fistman
  • 34,352
  • 5
  • 87
  • 159
  • Brilliant! First of all I have to thank Apple with all my hate. Like I always say, XCode is a piece of flaming crap that should be terminated and Apple has to show some love for developers. What kind of sick development team decide to throw "unknown error" if the error is known? Second I say that I am allocating just ONE sample buffer. Third, I would like to ask you how did you discover that? It may be useful in the future. THANKS. – Duck Mar 27 '17 at 22:34
  • 1
    I googled 536870211 which vindicated my belief that dealing with memory constraints is one of the hardest parts of video processing. Also, the iPad3 was notoriously short of memory. – Rhythmic Fistman Mar 27 '17 at 22:47
  • sorry bothering you again, but looking at my code do you see something I can do to minimize memory allocation? thanks – Duck Mar 28 '17 at 17:26
  • can you create a runnable project? – Rhythmic Fistman Mar 28 '17 at 20:27