title: How to fix CVPixelBuffer memory leak
body: <p>convert uiimages to mp4 using HJImagesToVideo (source code from github), but i fund it may have memory leak. more than 200 images converting, there will be memory warning, and then crash. the source code here:</p>
  
  <p><pre> </p>
  
  <code> + (void)writeImageAsMovie:(NSArray )array
                     toPath:(NSString)path
                       size:(CGSize)size
                        fps:(int)fps
         animateTransitions:(BOOL)shouldAnimateTransitions
          withCallbackBlock:(SuccessBlock)callbackBlock
      {
           NSLog(@"%@", path);
           NSError *error = nil;
           AVAssetWriter *videoWriter = [[AVAssetWriter alloc] initWithURL:[NSURL fileURLWithPath:path]
                                                             fileType:AVFileTypeMPEG4
                                                                error:&amp;error];
           if (error) 
           {
               if (callbackBlock) 
               {
                  callbackBlock(NO);
               }
               return;
           }
           NSParameterAssert(videoWriter);
  
  
           NSDictionary *videoSettings = @{AVVideoCodecKey: AVVideoCodecH264,
                                  AVVideoWidthKey: [NSNumber numberWithInt:size.width],
                                  AVVideoHeightKey: [NSNumber numberWithInt:size.height]};
  
           AVAssetWriterInput* writerInput = [AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeVideo
                                                                       outputSettings:videoSettings];
  
           AVAssetWriterInputPixelBufferAdaptor *adaptor = [AVAssetWriterInputPixelBufferAdaptor assetWriterInputPixelBufferAdaptorWithAssetWriterInput:writerInput
                                                                                                                   sourcePixelBufferAttributes:nil];
      NSParameterAssert(writerInput);
      NSParameterAssert([videoWriter canAddInput:writerInput]);
          [videoWriter addInput:writerInput];
  
          //Start a session:
          [videoWriter startWriting];
          [videoWriter startSessionAtSourceTime:kCMTimeZero];
  
          CVPixelBufferRef buffer;
          CVPixelBufferPoolCreatePixelBuffer(NULL, adaptor.pixelBufferPool, &amp;buffer);
  
          CMTime presentTime = CMTimeMake(0, fps);
  
          int i = 0;
          while (1)
          {
  
  
              if(writerInput.readyForMoreMediaData)
              {
  
                  presentTime = CMTimeMake(i, fps);
  
                  if (i &gt;= [array count]) 
                  {
                      buffer = NULL;
                  } 
                  else 
                  {
                      buffer = [HJImagesToVideo pixelBufferFromCGImage:[array[i] CGImage] size:CGSizeMake(480, 320)];
                  }
  
                  if (buffer) 
                  {
                  //append buffer
  
                      BOOL appendSuccess = [HJImagesToVideo appendToAdapter:adaptor
                                                            pixelBuffer:buffer
                                                                 atTime:presentTime
                                                              withInput:writerInput];
                      NSAssert(appendSuccess, @"Failed to append");
  
                      if (shouldAnimateTransitions &amp;&amp; i + 1 &lt; array.count) 
                      {
  
                          //Create time each fade frame is displayed
                          CMTime fadeTime = CMTimeMake(1, fps*TransitionFrameCount);
  
                          //Add a delay, causing the base image to have more show time before fade begins.
                          for (int b = 0; b &lt; FramesToWaitBeforeTransition; b++) 
                          {
                              presentTime = CMTimeAdd(presentTime, fadeTime);
                          }
  
                          //Adjust fadeFrameCount so that the number and curve of the fade frames and their alpha stay consistant
                          NSInteger framesToFadeCount = TransitionFrameCount - FramesToWaitBeforeTransition;
  
                          //Apply fade frames
                          for (double j = 1; j &lt; framesToFadeCount; j++) 
                          {
  
                               buffer = [HJImagesToVideo crossFadeImage:[array[i] CGImage]
                                                           toImage:[array[i + 1] CGImage]
                                                            atSize:CGSizeMake(480, 320)
                                                         withAlpha:j/framesToFadeCount];
  
                              BOOL appendSuccess = [HJImagesToVideo appendToAdapter:adaptor
                                                                    pixelBuffer:buffer
                                                                         atTime:presentTime
                                                                      withInput:writerInput];
                              presentTime = CMTimeAdd(presentTime, fadeTime);
  
                              NSAssert(appendSuccess, @"Failed to append");
                          }
                      }
  
                      i++;
                  } 
                  else 
                  {
  
                      //Finish the session:
                      [writerInput markAsFinished];
  
                      [videoWriter finishWritingWithCompletionHandler:^{
                          NSLog(@"Successfully closed video writer");
                          if (videoWriter.status == AVAssetWriterStatusCompleted)                                                   {
                               if (callbackBlock) {
                                  callbackBlock(YES);
                               }
                               } else {
                                if (callbackBlock) {
                                callbackBlock(NO);
                               }
                          }
                  }];
  
                      CVPixelBufferPoolRelease(adaptor.pixelBufferPool);
                      //CVPixelBufferRelease(buffer);
                      NSLog (@"Done");
                      break;
                  }
              }
  
  
           }
          }
  
  
  
  
       + (CVPixelBufferRef)pixelBufferFromCGImage:(CGImageRef)image
                                    size:(CGSize)imageSize
      {
         NSDictionary *options = @{(id)kCVPixelBufferCGImageCompatibilityKey: @YES,
                            (id)kCVPixelBufferCGBitmapContextCompatibilityKey: @YES};
         CVPixelBufferRef pxbuffer = NULL;
         CVReturn status = CVPixelBufferCreate(kCFAllocatorDefault, imageSize.width,
                                        imageSize.height, kCVPixelFormatType_32ARGB, (__bridge CFDictionaryRef) options,
                                        &amp;pxbuffer);
         NSParameterAssert(status == kCVReturnSuccess &amp;&amp; pxbuffer != NULL);
  
         CVPixelBufferLockBaseAddress(pxbuffer, 0);
         void *pxdata = CVPixelBufferGetBaseAddress(pxbuffer);
         NSParameterAssert(pxdata != NULL);
  
         CGColorSpaceRef rgbColorSpace = CGColorSpaceCreateDeviceRGB();
         CGContextRef context = CGBitmapContextCreate(pxdata, imageSize.width,
                                               imageSize.height, 8, 4*imageSize.width, rgbColorSpace,
                                               kCGImageAlphaNoneSkipFirst);
         NSParameterAssert(context);
  
         CGContextDrawImage(context, CGRectMake(0 + (imageSize.width-CGImageGetWidth(image))/2,
                                         (imageSize.height-CGImageGetHeight(image))/2,
                                         CGImageGetWidth(image),
                                         CGImageGetHeight(image)), image);
         CGColorSpaceRelease(rgbColorSpace);
         CGContextRelease(context);
  
         CVPixelBufferUnlockBaseAddress(pxbuffer, 0);
  
         return pxbuffer;
      } 
  </code></pre>
  
  <p></p>