如何使用AVFoundation设置逐帧生成video的方向?

我正在编写一个iPhone应用程序,它从摄像头获取video,通过一些OpenGL着色器代码运行它,然后使用AVFoundation将输出写入video文件。 该应用程序运行在lanscape方向(任一),因此所有录制的video应该是风景。

在开始录制以获得正确的video之前,我使用的当前代码是:

 [[self videoWriterInput] setTransform:CGAffineTransformScale(CGAffineTransformMakeRotation(M_PI), -1.0, 1.0)]; 

videoWriterInput是AVAssetWriterInput的一个实例,其目的是为了补偿OpenGL的景观模式和反思方向。

这会产生在Quicktime播放器上下载和播放时播放正确的video。 但是,如果将录制的video添加到iPhone照片库中,则缩略图可以正确显示,但如果手机处于横向模式,video将播放旋转90度。 如果手机处于肖像状态,video将正确播放,但会水平裁剪以适应纵向尺寸。

根据这个Apple技术笔记 ,我用于处理video帧的AVCaptureVideoDataOutput的捕获输出不支持设置video方向。

有没有人成功地logging了景观生成的video,可以添加到iPhone库,并在横向上正确播放,如果是这样的话?

您的文章打开了我的眼睛关于苹果video应用程序如何播放video。 我用这个设备在四个方向上logging了几个项目。 他们都打得很好。 我只是注意到,video应用程序不支持在像册应用程序中的播放器旋转。 video应用程序希望您保持设备(至less我的iPod touch)横向。 我做了一些肖像录音,将它们添加到iTunes中,包括使用Apple相机应用程序创build的所有内容都不会在将设备旋转到纵向时旋转。

无论如何…

我的应用程序是一个时间stream逝的应用程序,不会像你正在做的任何额外的处理框架,所以下面的YMMV。 我有我的应用程序设置,以便它不旋转设备旋转窗口。 这样我总是处理设备的一个方向。 我使用AVFoundation从videostream中抓取每一个第N帧,并写出来。

当我开始录制时,我做了以下工作。

 inputWriterBuffer = [AVAssetWriterInput assetWriterInputWithMediaType: AVMediaTypeVideo outputSettings: outputSettings]; // I call this explicitly before recording starts. Video plays back the right way up. [self detectOrientation]; inputWriterBuffer.transform = playbackTransform; 

detectOrientation调用以下方法。 这里我已经减less了实际的代码。 在我的应用程序中,我也旋转一些button,所以注意他们没有得到相同的转换。 要注意的是我如何设置playbackTransform伊娃。

 -(void) detectOrientation { CGAffineTransform buttonTransform; switch ([[UIDevice currentDevice] orientation]) { case UIDeviceOrientationUnknown: NULL; case UIDeviceOrientationFaceUp: NULL; case UIDeviceOrientationFaceDown: NULL; break; case UIDeviceOrientationPortrait: [UIButton beginAnimations: @"myButtonTwist" context: nil]; [UIButton setAnimationDuration: 0.25]; buttonTransform = CGAffineTransformMakeRotation( ( 0 * M_PI ) / 180 ); recordingStarStop.transform = buttonTransform; [UIButton commitAnimations]; playbackTransform = CGAffineTransformMakeRotation( ( 90 * M_PI ) / 180 ); break; case UIDeviceOrientationLandscapeLeft: [UIButton beginAnimations: @"myButtonTwist" context: nil]; [UIButton setAnimationDuration: 0.25]; buttonTransform = CGAffineTransformMakeRotation( ( 90 * M_PI ) / 180 ); recordingStarStop.transform = buttonTransform; [UIButton commitAnimations]; // Transform depends on which camera is supplying video if (theProject.backCamera == YES) playbackTransform = CGAffineTransformMakeRotation( 0 / 180 ); else playbackTransform = CGAffineTransformMakeRotation( ( -180 * M_PI ) / 180 ); break; case UIDeviceOrientationLandscapeRight: [UIButton beginAnimations: @"myButtonTwist" context: nil]; [UIButton setAnimationDuration: 0.25]; buttonTransform = CGAffineTransformMakeRotation( ( -90 * M_PI ) / 180 ); recordingStarStop.transform = buttonTransform; [UIButton commitAnimations]; // Transform depends on which camera is supplying video if (theProject.backCamera == YES) playbackTransform = CGAffineTransformMakeRotation( ( -180 * M_PI ) / 180 ); else playbackTransform = CGAffineTransformMakeRotation( 0 / 180 ); break; case UIDeviceOrientationPortraitUpsideDown: [UIButton beginAnimations: @"myButtonTwist" context: nil]; [UIButton setAnimationDuration: 0.25]; buttonTransform = CGAffineTransformMakeRotation( ( 180 * M_PI ) / 180 ); recordingStarStop.transform = buttonTransform; [UIButton commitAnimations]; playbackTransform = CGAffineTransformMakeRotation( ( -90 * M_PI ) / 180 ); break; default: playbackTransform = CGAffineTransformMakeRotation( 0 / 180 ); // Use the default, although there are likely other issues if we get here. break; } } 

作为一个方面说明,因为我想要的方法调用时,设备旋转,我已经closures自动旋转,我有我的viewDidLoad方法中的以下内容。

 [[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(detectOrientation) name:@"UIDeviceOrientationDidChangeNotification" object:nil]; 

这是我在这个SOF问答中发现的一个提示。

简单得多

在你的顶点着色器中:

统一浮动preferredRotation; 。 。 。 cos(优选旋转),-sin(优选旋转),0.0,0.0,sin(优选旋转),cos(优选旋转) ;

 /* 90-degrees mat4 rotationMatrix = mat4( cos(preferredRotation), -sin(preferredRotation), (1.0 - cos(preferredRotation)) - sin(preferredRotation), 0.0, -sin(preferredRotation), cos(preferredRotation), 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0); 

在调用着色器的视图或视图控制器中:

if([videoTrack statusOfValueForKey:@“preferredTransform”error:nil == AVKeyValueStatusLoaded){CGAffineTransform preferredTransform = [videoTrack preferredTransform]; self.playerView.preferredRotation = -1 * atan2(preferredTransform.b,preferredTransform.a);

…等等…