UIImagePickerController: Getting image capture fro

2019-03-30 03:30发布

问题:

I'm trying to extract a frame from a video as an image. The video is recorded using UIImagePickerController.

When the video has been recorded I get its URL and load it using AVURLAsset. Then I create a AVAssetReader and AVAssetReaderTrackOutput to get the individual frames.

When I get the frames as CMSampleBufferRef's I pass them to Apple's imageFromSampleBuffer method which should return a UIImage. This method worked fine when I was getting frames using an AVCaptureSession but when I use a video recorded via UIImagePickerController then this line returns 0x0:

CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer); 

Where sampleBuffer is the CMSampleBufferRed that I pass.

I checked the value of sampleBuffer via the debugger and it looked ok (wasn't 0x0). Is there any reason why CMSampleBufferGetImageBuffer would return 0x0?

Or alternatively is there another way to extract a single video frame from a MOV file and save it as a UIImage?

Thanks.

回答1:

I found the solution. You have to set the pixel format in the settings passed when you initialize an AVAssetReaderTrackOutput.

I passed the following settings dictionary:

NSString* key = (NSString*)kCVPixelBufferPixelFormatTypeKey;
NSNumber* value = [NSNumber numberWithUnsignedInt:kCVPixelFormatType_32BGRA];
NSDictionary* videoSettings = [NSDictionary dictionaryWithObject:value forKey:key]; 

Hope this helps someone else.



回答2:

I did it like this some time ago.

    func getPicture() -> UIImage {



        let imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer)!

        var videoWidth = CVPixelBufferGetWidth(imageBuffer)
        var videoHeight = CVPixelBufferGetHeight(imageBuffer)



        CVPixelBufferLockBaseAddress(imageBuffer, CVPixelBufferLockFlags(rawValue: 0))

        // Creating an image from a imageBuffer, a frame.
        let baseAddress = CVPixelBufferGetBaseAddress(imageBuffer)
        let bytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer) 
        let colorSpace  = CGColorSpaceCreateDeviceRGB()  
        var bitmapInfo  = CGBitmapInfo.byteOrder32Little.rawValue
        bitmapInfo |= CGImageAlphaInfo.premultipliedFirst.rawValue 


        let context = CGContext(data: baseAddress, width: videoWidth, height: videoHeight, bitsPerComponent: 8, bytesPerRow: bytesPerRow, space: colorSpace, bitmapInfo: bitmapInfo)!

        let frameImage =   context.makeImage()!  // This is a CGImage
        let image =  UIImage(cgImage: frameImage) 

        return image

    }