0

I'm writing a utility that exports MP4 video from a series of black and white images using AVAssetWriter, by suppling frames via an AVAssetWriterInputPixelBufferAdaptor and its associated CVPixelBuffer. I want to add the option to choose a color, and multiply each frame by that color, yielding the colorized image. Because I'm using a CGContext to write into a pixel buffer for each frame, I figured that would be as easy as modifying my existing (perfectly working) loop so that instead of drawing the one image into the context, I could add the additional steps to draw the color into the context and change blend modes.

 let rect = CGRect(x: 0, y: 0, width: 400, height: 300)
 context.setFillColor(.init(red: 1, green: 0, blue: 0, alpha: 1))
    
    for frameNumber in range {
        let frameTime = CMTimeMake(value: Int64(frameNumber - range.lowerBound), timescale: Int32(30))
        // Find the cgImage for this frame
        let cgImage = imageForFrame(frameNumber)!
        
        // Paint the canvas with the color.
        context.setBlendMode(.normal)
        context.fill(rect)
        
        // Multiply the bitmap to yield a colored image.
        context.setBlendMode(.multiply)
        context.draw(cgImage, in: rect)
        context.flush()
        
        while (!assetWriterInput.isReadyForMoreMediaData) { }
        assetWriterAdaptor.append(pixelBuffer, withPresentationTime: frameTime)
    }

The results I'm getting indicate that the drawing operations are not complete at the time of the final line, where the CVPixelBuffer's contents are copied into the AssetWriterAdaptor.

A bitmap frame with a partially incomplete multiply operation.

In this example frame, it seems that the initial command to fill the rectangle with red pixels completes, but drawing in the CGImage is not complete at the time the buffer is read. If I try changing the draw order or blend modes, I get similar results, all pointing to the second draw operation being unfinished.

Is there a way I can ensure that the drawing operations have been completed? I figured that flushing the context would block my thread until those operations were complete, but it doesn't seem to do so.

Hayden McCabe
  • 494
  • 2
  • 14

0 Answers0