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.
Why hack it when it's very easy. Just set automaticallyAdjustVideoMirroring of your AVCaptureConnection then set it manually.
aPreviewLayer.connection.automaticallyAdjustsVideoMirroring = NO;
aPreviewLayer.connection.videoMirrored = YES;
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With