Search code examples
iosvideo-capturecgaffinetransformavmutablecompositionfront-camera

Flip the video recorded with front facing camera along horizontal axis in IOS


I am trying to un-mirror the mirror effect created by iPhone’s front facing camera while recording video. Basically, I want to flip the video captured by front facing camera along the horizontal axis, so that the final edited video doesn’t not have the mirror effect like the inbuilt camera app does. I am using AVCaptureSession for recording videos.

// 3.1 - Create AVMutableVideoCompositionInstruction
    AVMutableVideoCompositionInstruction *mainInstruction = [AVMutableVideoCompositionInstruction videoCompositionInstruction];
    mainInstruction.timeRange = CMTimeRangeMake(kCMTimeZero, self.videoAsset.duration);

// 3.2 - Create an AVMutableVideoCompositionLayerInstruction for the video track and fix the orientation.
AVMutableVideoCompositionLayerInstruction *videolayerInstruction = [AVMutableVideoCompositionLayerInstruction videoCompositionLayerInstructionWithAssetTrack:videoTrack];
AVAssetTrack *videoAssetTrack = [[self.videoAsset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0];

UIImageOrientation videoAssetOrientation_  = UIImageOrientationUp;
BOOL isVideoAssetPortrait_  = NO;
CGAffineTransform videoTransform = videoAssetTrack.preferredTransform;
if (videoTransform.a == 0 && videoTransform.b == 1.0 && videoTransform.c == -1.0 && videoTransform.d == 0)
{
    videoAssetOrientation_ = UIImageOrientationRight;
    isVideoAssetPortrait_ = YES;
}
if (videoTransform.a == 0 && videoTransform.b == -1.0 && videoTransform.c == 1.0 && videoTransform.d == 0)
{
    videoAssetOrientation_ =  UIImageOrientationLeft;
    isVideoAssetPortrait_ = YES;
}
if (videoTransform.a == 1.0 && videoTransform.b == 0 && videoTransform.c == 0 && videoTransform.d == 1.0)
{
    videoAssetOrientation_ =  UIImageOrientationUp;
}
if (videoTransform.a == -1.0 && videoTransform.b == 0 && videoTransform.c == 0 && videoTransform.d == -1.0)
{
    videoAssetOrientation_ = UIImageOrientationDown;
}

//*********below are the transforms I am applying in which you might be interested in**********

CGAffineTransform t = CGAffineTransformMakeTranslation(videoAssetTrack.naturalSize.height, 0.0);
t = CGAffineTransformMakeRotation(degreesToRadians(90.0));
t = CGAffineTransformMakeScale(-1, 1);  //this line is where I am having problem

[videolayerInstruction setTransform:t atTime:kCMTimeZero];
[videolayerInstruction setOpacity:1.0 atTime:self.videoAsset.duration];


// 3.3 - Add instructions
mainInstruction.layerInstructions = [NSArray arrayWithObjects:videolayerInstruction,nil];

AVMutableVideoComposition *mainCompositionInst = [AVMutableVideoComposition videoComposition];


CGSize naturalSize;
if(isVideoAssetPortrait_)
{
    naturalSize = CGSizeMake(videoAssetTrack.naturalSize.height, videoAssetTrack.naturalSize.width);
}
else
{
    naturalSize = videoAssetTrack.naturalSize;
}

float renderWidth, renderHeight;
renderWidth = naturalSize.width;
renderHeight = naturalSize.height;
mainCompositionInst.renderSize = CGSizeMake(renderWidth, renderHeight);
mainCompositionInst.instructions = [NSArray arrayWithObject:mainInstruction];
mainCompositionInst.frameDuration = CMTimeMake(1, 30);

In the above code when I remove the scaling transform t = CGAffineTransformMakeScale(-1, 1);

I get video frames with proper orientation but they are not flipped. When I apply the scaling transform I get blank video frames. Currently, I am doing this only for portrait mode videos.

If anyone has any knowledge regarding this please share. Thank you in advance.


Solution

  • You made a small mistake with affine transformations.

    Replace the code:

    CGAffineTransform t = CGAffineTransformMakeTranslation(videoAssetTrack.naturalSize.height, 0.0);
    t = CGAffineTransformMakeRotation(degreesToRadians(90.0));
    t = CGAffineTransformMakeScale(-1, 1);  //this line is where I am having problem
    

    With corrected code:

    CGAffineTransform t = CGAffineTransformMakeScale(-1.0f, 1.0f);
    t = CGAffineTransformTranslate(t, -videoAssetTrack.naturalSize.width, 0);
    t = CGAffineTransformRotate(t, (degreesToRadians(90.0)));
    t = CGAffineTransformTranslate(t, 0.0f, -videoAssetTrack.naturalSize.width);