AVFoundation - how to mirror video from webcam - Mac OS X

avfoundation, macos, webcam-capture

Solution

You can add a transform on the preview layer to flip x value of the frames before they get to the preview window.

[[self previewLayer] setTransform:CATransform3DMakeScale(-1, 1, 1)];

Then you can run the recorded video through export session and do the same transformation. That way the video preview will match the final recorded video. Bit of a hack, but it gets the same results.

Problem

I am trying to mirror video received from webcam on mac os x. I would like to avoid doing a manual flip/tranform after receiving the video buffer . So, I want to setup `AVCaptureSession` such that video buffer received in `captureOutput` method of `AVCaptureVideoDataOutputSampleBufferDelegate` is mirrored by AVFoundation itself. I don't want to use the preview layer. On an iMac(10.8.5), to mirror video, `AVCaptureConnection isVideoMirroringSupported` is successfully tested before setting the `videoMirrored` property. But video buffer received in `captureOutput` delegate isn't mirrored. Note: Video mirroring on iOS was successful, when I followed this SO answer. But it isn't helping on mac os x. Code used is below. Error checking is left out for this post. ``` //create session _session = [[AVCaptureSession alloc] init]; //get capture device _device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo]; //create sesion input NSError * error; _sessionInput = [AVCaptureDeviceInput deviceInputWithDevice:_device error:&error]; //create session output _sessionOutput = [[AVCaptureVideoDataOutput alloc] init]; [_sessionOutput setAlwaysDiscardsLateVideoFrames:YES]; [[_sessionOutput connectionWithMediaType:AVMediaTypeVideo] setEnabled:YES]; NSDictionary *videoSettings = [NSDictionary dictionaryWithObject: [NSNumber numberWithUnsignedInt:kCVPixelFormatType_32BGRA] forKey:(id)kCVPixelBufferPixelFormatTypeKey]; [_sessionOutput setVideoSettings:videoSettings]; //serial queue to process video frames dispatch_queue_t videoOutputQueue = dispatch_queue_create("deviceeraQueue", DISPATCH_QUEUE_SERIAL); [_sessionOutput setSampleBufferDelegate:self queue:videoOutputQueue]; //begin session configuration [_session beginConfiguration ]; //input and output for session if( [_session canAddInput:_sessionInput]) { [_session addInput:_sessionInput]; } if( [_session canAddOutput:_sessionOutput]) { [_session addOutput:_sessionOutput]; } //set video mirroring AVCaptureConnection* avConnection = [_sessionOutput connectionWithMediaType:AVMediaTypeVideo]; if( [avConnection isVideoMirroringSupported]) { avConnection.videoMirrored = YES; NSLog(@"Video mirroring Support: YES"); // this line is printed } else { NSLog(@"Video mirroring Support: NO"); } //set session preset [_session setSessionPreset:AVCaptureSessionPreset640x480]; [ _session commitConfiguration ]; ........... ........... - (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection { ......... //sampleBuffer is not mirrored video ........ ``` Of lesser importance 1 - though C++, I also tried looking into OpenCV's VideoCapture implementation for way to mirror video. But, OpenCV don't mirror video from Mac(uses flip). Left is libVlc/V4L. Of lesser importance 2 - In slide 73 of this 2010 wwdc apple presentation (3Mb pdf), there is a mention that `setVideoOrientation` is not supported on 'AVCaptureVideoDataOutput` connection. But in 2013, apple docs are updated and supports this method.

Original source

Related problems